新建maven工程xxx-search
maven目录结构
- xxx-search
-
- xxx-search-api
- com.xxx.search.api 接口定义层
- dto
- param
- interfaces
- com.xxx.search.api 接口定义层
- xxx-search-service
- com.xxx.search.service 实现层
- ApiImpl
- common
- domain
- com.xxx.search.service 实现层
- xxx-search-web
- com.xxx.search.web 调用层 小前台
- controller
- common
- feign 远程调用
- fallback 调用失败 兜底方法
- vo
- param
- com.xxx.search.web 调用层 小前台
- xxx-search-api
-
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
加注解
- 启动类添加注解 @EnableDiscoveryClient
添加配置
@Configuration
@RequiredArgsConstructor
public class FeignConfiguration implements RequestInterceptor {
private final BaseBean baseBean;
@Bean
Logger.Level feignLoggerLevel() {
//这里记录所有,根据实际情况选择合适的日志level
return Logger.Level.FULL;
}
@Override
public void apply(RequestTemplate template) {
//请求头 添加服务名字
template.header("SERVER", baseBean.getName());
}
}
yml文件配置
ribbon:
# 设置连接超时时间 单位毫秒
ConnectTimeout: 40000
# 设置读取超时时间 单位毫秒
ReadTimeout: 30000
# 对所有操作请求都进行重试
OkToRetryOnAllOperations: false
# 对当前实例的重试次数
# MaxAutoRetries: 1
# 切换实例的重试次数
MaxAutoRetriesNextServer: 0
#获取负载均衡器服务列表缓存 单位毫秒
ServerListRefreshInterval: 5000
实现
1.api层定义接口
/**
* 测试接口
* @return TestDto
*/
@RequestMapping(value="/test", method= RequestMethod.GET)
R getTestDto();
2.service层实现api接口
@RestController
@RequiredArgsConstructor
@Slf4j
public class TestApiImpl implements TestApi{
@Override
public R getTestDto() {
return R.ok();
}
}
3.web层feign调用
feign通过服务名"search-server"调用,必须注册到相同的nacos中
@Component
@FeignClient(value = "search-server",fallbackFactory = FtestApiFallback.class)
public interface FtestApi extends TestApi {
}
兜底的方案 比如限流,熔断
@Component
public class FtestApiFallback implements FallbackFactory<FtestApi> {
@Override
public FtestApi create(Throwable throwable) {
return new FtestApi() {
@Override
public R getTestDto() {
return null;
}
}
}
前端接口请求
@RestController
@RequiredArgsConstructor
public class TestController {
private final FtestApi ftestApi;
@GetMapping("/test")
private R getTest(){
R testDto = ftestApi.getTestDto();
String ok = R.isOk(testDto, String.class);
return R.ok(ok);
}
}
整合Sentinel
- 演示在service层流控规则和授权规则
添加依赖
<!-- sentinel Push模式依赖 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
添加配置,限流统一返回
@Component
public class MyUrlBlockHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws Exception {
String msg = null;
if (ex instanceof FlowException) {
msg = "限流了";
} else if (ex instanceof DegradeException) {
msg = "降级了";
} else if (ex instanceof ParamFlowException) {
msg = "热点参数限流";
} else if (ex instanceof SystemBlockException) {
msg = "系统规则(负载/...不满足要求)";
} else if (ex instanceof AuthorityException) {
msg = "授权规则不通过";
}
// http状态码 只能是错误码 才能被调用方feign FallbackFactory拦截到
response.setStatus(423);
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Type", "application/json;charset=utf-8");
response.setContentType("application/json;charset=utf-8");
new ObjectMapper()
.writeValue(
response.getWriter(),
R.error(ErrorEnum.SYSTEM_OFTEN.code(),msg)
);
}
自定义授权规则
@Configuration
public class RequestOriginParserDefinition implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest request) {
//上游服务名字 上游可以通过feign.RequestInterceptor方法实现
return request.getHeader("SERVER");
}
}
yml文件添加
# 熔断限流
sentinel:
transport:
dashboard: ${wfx.ip}:8080
#取消控制台懒加载
eager: true
datasource:
#流控规则
ds1:
nacos:
server-addr: ${wfx.ip}:8848
data-id: ${spring.application.name}-${spring.profiles.active}-flow
groupId: ${spring.application.name}-group
data-type: json
rule-type: flow
#访问控制规则
ds2:
nacos:
server-addr: ${wfx.ip}:8848
data-id: ${spring.application.name}-${spring.profiles.active}-authority
groupId: ${spring.application.name}-group
data-type: json
rule-type: authority
#开启 Feign 对 Sentinel 的支持
feign:
sentinel:
enabled: true
在nacos配置管理添加流控配置文件 search-server-dev-flow 格式json
[
{
#资源名,即限流规则的作用对象
"resource": "/test",
#来源应用
"limitApp": "search-web",
#限流阈值类型,QPS 或线程数
"grade": 1,
#限流阈值
"count": 1,
#根据调用关系选择策略
"strategy": 0,
#流量控制
"controlBehavior": 0
}
]
在nacos配置管理添加授权配置文件 search-server-dev-authority 格式json
[
{
#资源名,即限流规则的作用对象
"resource": "/test",
#来源应用
"limitApp": "search-web",
#0白名单1黑名单
"strategy":"0",
##流量控制
"controlBehavior": 0
}
]
启动web service
sentinel控制台出现这两种控制
前端请求/test接口 是web小前台通过feign调用下游service的api接口,下游处理数据,在返回web层,下游限流了,或者授权不通过,都会到web层的FtestApiFallback这个类处理