Feign是一种新的使用http进行远程调用的方式。
1)使用方法:在启动类书写一个方法,然后通过url在service中进行调用
String url = "http://userservice/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);
1)是一种申明式的http客户端,作用是帮助我们优雅实现http请求的发送,解决上面提到的问题。
2) 实现逻辑还是差不多的,都是为了生成一个url进行远程调用。只不过在Feign中,采用申明式结构进行URL的拆分再组装。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
@FeignClient("userservice")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
上述定义Feign客户端中,包含很多信息:
(1)服务名称:userservice
(2)请求方式:Get
(3)请求路径:/user/{id}
(4)请求参数:Long id
(5)返回对象:User
第二行红色,两行给为一行了!
String url="http://localhost:8081/user/"+order.getUserId(); //获取用户的id信息
User user=restTemplate.getForObject(url,User.class); //通过url进行远程调用,并把得到的数据变为user格式
一般使用比较多的是:日志级别的修改,共有四种级别:NONE,BASIC,HEADERS,FULL,一般默认选用NONE即可
主要是在Feign底层进行优化,即采用具有连接池的原理。
Feign底层的客户端实现:
1)URLConnection:默认实现,不支持连接池(性能一般)
2)Apache HttpClient:支持连接池(不用每次都请求链接,效率更高)
3)OKHttp:支持连接池
优化的方向:
1)使用连接池代替默认的URLConnection
2)日志级别的修改:使用NONE和BASIC,更加简洁。
Feign添加HttpClient的支持,故需要引入依赖和配置连接池
<!--feign-api的依赖 -->
<dependency>
<groupId>cn.itcast.demo</groupId>
<artifactId>feign-api</artifactId>
<version>1.0</version>
</dependency>
feign:
client:
config:
default: # default全局的配置
loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
httpclient:
enabled: true # 开启feign对HttpClient的支持
max-connections: 200 # 最大的连接数
max-connections-per-route: 50 # 每个路径的最大连接数
<!--引入feign的统一api-->
<dependency>
<groupId>cn.itcast.demo</groupId>
<artifactId>feign-api</artifactId>
<version>1.0</version>
</dependency>
@EnableFeignClients(basePackages = "cn.itcast.feign.clients")
2)指定FeignClient字节码(小范围)
@EnableFeignClients(clients = {UserClient.class})
1. 网关的作用
1)身份认证和权限校验等:不是什么用户通过链接都能够访问的,需要指定的用户名等情况,或者需要某一些权限处于开启状态;
2)服务路由和负载均衡:将用户请求路由到微服务,并实现负载均衡。网关具有负载均衡的作用,故不需要自己去配置Ribbon
3)请求限流:同一个时刻,对于服务的访问,限制流量,不能够过于频繁访问。
2. 网关技术的实现
目前SpringCloud中,网关的实现包括两种:
1)gateway:SpringCloudGateWay则属于Spring5中提供的WebFlux,属于响应式编程的实现,具有更好的性能。
2)zuul:基于Servlet的实现,属于阻塞式的编程
3)区别:响应式编程和阻塞式编程。
<!--网关依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
1) 路由id:路由的id,是路由的唯一表示
2)路由目标(uri):路由的目标地址,http代表固定地址,lb代表根据服务名负载均衡
3)路由断言(predicates):判断路由的规则,例如Path=/user/**,判断路径是否以/user开头,如果是则符合
4)路由过滤器(filters):对请求和相应做处理
上述配置中的断言都是通过断言工厂进行执行的:读取用户定义的断言条件,对请求做出判断
1)我们在配置文件中书写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件
2)例如Path=/user/**是按照路径匹配,规则是org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类处理的
3)像这样的断言工厂还有好几十个,可自行通过说明进行使用。
1. 过滤器工厂介绍
在路由确定之后会通过过滤器进行过滤操作,再通过负载均衡分配到具体的服务中去。
过滤器可以对进入网关的请求和微服务返回的响应做处理
2. 过滤器工厂种类
Spring提供了31种不同的路由过滤器工厂
3. 过滤器工厂使用案例
1)要求:给所有进入userservice的请求,添加一个请求头:Truth=itcast is freaking awesome!
2)实现步骤
(1)在gateway中修改配置文件,给userservice的路由添加过滤器
spring:
cloud:
gateway:
routes: # 网关路由配置
- id: user-service #路由id
uri: lb://userservice #路由路径
predicates: #路由断言
- Path=/user/‘**’ #判断是否存在/user路径
filters: # 过滤器,带有s,可以有多个操作
- AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头
(2)如果要对所有的路由都生效,故需要将过滤器工厂写到default下面,格式如下:
1)全局过滤器能够处理一切进入网关的请求和微服务相应,与GatewayFilter的作用是一致的。
2)与GatewayFilter的区别:GatewayFilter是通过配置文件实现的,处理逻辑固定;GlobalFilter的逻辑需要自己写代码实现,更加灵活!
1)实现GlobalFilter接口:
全局过滤器 GlobalFilter
public interface GlobalFilter {
/**
* 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
*
* @param exchange 请求上下文,里面可以获取Request、Response等信息
* @param chain 用来把请求委托给下一个过滤器
* @return {@code Mono} 返回标示当前过滤器业务结束
*/
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
2)添加@Order注解或者实现Ordered接口:为了给过滤器进行优先级排序
3)编写处理逻辑
4)添加注解@Component,注入bean中,方便使用
参数中是否有authorization,
authorization参数值是否为admin
五步走:
(1)获取请求参数
(2)获取authorization参数
(3)校验
(4)放行
(5)禁止访问/结果处理
三种过滤器:当前路由过滤器,DefaultFilter过滤器,GlobalFilter
网关其实并不需要改变其他服务中的代码,只是一个额外的功能,单独在网关服务中,其实现的原理有:
1)首先生成一个网关服务,添加启动类
2)引入注册发现依赖,引入网关依赖
3)网关的过滤作用在配置文件中声明实现(路由过滤器和defaultfilter,都是申明式的)
4)通过GlobalFilter过滤器实现:通过添加一个类,继承GlobalFilter接口,再书写逻辑,可以更加灵活的操作。
在微服务体系中,配置文件和依赖非常重要
参考文献
1)黑马程序员SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课
用于复制