文章目录
服务调用为什么使用http协议, 而不是rpc
- 支持异构平台;
- 无状态, 弱依赖, 可插拔;
RestTemplate
-
restTemplate.getForObject();
-
restTemplate.getForEntity();
-
restTemplate.postForEntity();
-
restTemplate.postLocation();
-
ClentHttpRequestInterceptor 是 RestTemplate 的一个扩展点;
package com.go.cn.conf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;
public class LoggingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
logger.info("rest_template 被拦截 ==>>");
logger.info("uri={}", request.getURI());
ClientHttpResponse response = execution.execute(request, body);
logger.info("response={}", response.getHeaders());
return response;
}
}
---使用---
restTemplate.getInterceptors().add(new LoggingClientHttpRequestInterceptor());
OpenFeign
- feign 本身不支持SpringMVC的注解, OpenFeign 是spring-cloud在fegin的基础上支持了SpringMVC的注解;
使用步骤
- 依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
-
启动类添加:
@EnableFeignClients
-
消费方 service 类上加注解:
@FeignClient(name = "provider-name")
;
使用方式
- 原生使用: name+url; //todo
- 节后Eureka: name 写eureka 的服务名;
- 使用jar包, 面向java 的 interface 开发;
- 传参调用: 调用方/消费方 方法要加(@RequestParam(“param_name”)) 多个参数就写多个
- Feign默认所有带参数的请求都是Post请求,@GetMapping 也 默认发送 post 请求需要 修改: 需要引入 feign-httpclient 包(6-00:30):
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
- 之后就和 @GetMapping/@PostMapping对应;
- get 请求带参数注意使用
@RequestParam("param_name")
- feign 调用传map: (@RequestParam Map<String, Object> map); 接收方controller 也是: (@RequestParam Map<String, Object> map);
- feign 在调用方写的 mvc 的注解要和 被调用方-provider 接口上写的注解保持一致;
- feign post 调用传对象: 必须使用 @RequestBody user-api, postPerson
feign 配置
-
feign的默认配置类是:
org.springframework.cloud.openfeign.FeignClientsConfiguration
。默认定义了feign使用的编码器,解码器等。 -
允许使用
@FeignClient
的configuration
的属性自定义Feign配置。自定义的配置优先级高于默认的FeignClientsConfiguration。
feign 配置权限认证
- provider 方开启权限认证:
- 1 依赖:
<!-- 权限认证, RestTemplate 调用报错时可以注释掉 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 2 java配置类:
package com.go.cn.inner;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 关闭csrf
http.csrf().disable();
// 表示所有的访问都必须认证,认证处理后才可以正常进行
http.httpBasic().and().authorizeRequests().anyRequest().fullyAuthenticated();
// 设置为无状态
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
- 配置文件:
spring:
application:
name: provider
security:
user:
name: root
password: root
- 调用方配置,有两种方式:1-自定义配置类,2-增加拦截器。
- 1-自定义配置类:
package com.go.cn.conf;
import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.context.annotation.Bean;
public class FeignAuthConfiguration {
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("root", "root");
}
}
---@FeignClient.configuration 属性配置---
@FeignClient(name = "provider", configuration = FeignAuthConfiguration.class)
- 2-拦截器:
package com.go.cn.conf;
import feign.RequestInterceptor;
import feign.RequestTemplate;
public class MyBasicAuthRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
// cm9vdDpyb290 为 root:root base64 编码后的字符串,可使用 https://base64.us/ 在线验证
template.header("Authorization", "Basic cm9vdDpyb290");
}
}
--- 配置文件 ---
feign:
client:
config:
provider: # 被调用方的服务名
request-interceptors:
- com.go.cn.conf.MyBasicAuthRequestInterceptor
超时、压缩配置
- 配置连接时间和超时时间
feign:
client:
config:
provider-name: # 指定服务名称
connect-timeout: 5000
read-timeout: 5000
logger-level: full
---
feign:
client:
default-to-properties: false # properties配置比Java代码优先级高,可通过此配置设置java代码优先级高。
config:
default: # 通用配置
connect-timeout: 5000
read-timeout: 5000
logger-level: full
-
压缩配置:
-
provider 端:
server:
compression:
enabled: true
- consumer 端配置:
feign:
compression:
request: # 配置请求GZIP压缩
enabled: true
# 字节
min-request-size: 100
response: #配置响应GZIP压缩
enabled: true
feign 内置ribbon
-
建立连接超时:
ribbon.ConnectTimeOut
-
业务逻辑超时: ReadTimeout
-
设置重试次数: 如下面示例配置
-
ribbon重试机制,请求失败后,每隔6秒会重新尝试;6s 间隔, 不调用异常的服务, 使用其他的服务
-
Feign默认支持Ribbon;Ribbon的重试机制和Feign的重试机制有冲突,所以源码中默认关闭Feign的重试机制,使用Ribbon的重试机制;
-
示例配置:
ribbon:
# ribbon 超时配置
# 连接超时时间(ms)
ConnectTimeout: 1000
ReadTimeout: 6000
# 重试配置
# 同一台实例最大重试次数,不包括首次调用
MaxAutoRetries: 1
# 重试负载均衡其他的实例最大重试次数,不包括首次调用
MaxAutoRetriesNextServer: 1
# 是否所有操作都重试
OkToRetryOnAllOperations: false