HZERO微服务平台10: 代码分析之admin服务刷新路由、权限、swagger的过程 .md
2021/12/1 23:36:45
本文主要是介绍HZERO微服务平台10: 代码分析之admin服务刷新路由、权限、swagger的过程 .md,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录- 整体流程
- 权限刷新
- 自动刷新权限
- 手动刷新权限
- 权限刷新报错: parse_permission_data.failure
- 路由刷新
- 路由配置
- 如果开启了context-path, 路由配置需注意
- 业务服务路由的name或path重复
- 手动刷新路由报错: http transport failed, ExceptionResponse: For input string: "80,80"
admin服务接收到业务服务注册信息, 负责完成路由刷新、权限刷新、swagger信息刷新的过程;
整体流程
业务服务调用admin的注册接口:
/service-init-registry/register ServiceInitRegistryEndpoint#register RestServiceInitRegistry#register assertHealth(service); //只判断服务的状态, 如果up就把服务添加到启动成功的列表里 serviceInitRegistryRepository.add(service);
其中的ServiceInitRegistryRepository
接口:
维护需要初始化(未刷新路由、权限、swagger)的服务信息; 具体实现:RedisServiceInitRegistryRepository
, 存储在redis db1 hadm.services-to-init
;
其中的RestServiceInitRegistry
类:
public class RestServiceInitRegistry implements ServiceInitRegistry, SmartLifecycle { ... RestServiceInitRegistry#start //SmartLifecycle.start, 应用启动成功后自动执行; RestServiceInitRegistry#doStart this.initExecutor = new ThreadPoolExecutor( ... //服务刷新执行器, 执行刷新任务; this.checkExecutor = new ThreadPoolExecutor( ... //检查执行器, while循环检查, 负责清理已下线的过期服务、如果检查到未刷新服务唤醒服务刷新线程(initExecutor)
initExecutor
的流程;
RestServiceInitRegistry#doStart this.initExecutor.execute(() -> { init(getUnInitializedServices()) //刷新未初始化的服务 ServiceInitRegistry#init RestServiceInitRegistry#doInit RestServiceInitRegistry#executeInit //初始化链, 调用刷新链 buildInitChain().doChain(context); //依次执行InitFilter的实例 RouteInitFilter PermissionInitFilter SwaggerInitFilter
任务最终执行是责任链/过滤链模式, 相关代码: ...admin.infra.chain
包、InitFilter、InitChain、DefaultInitChain、InitChainFactoryBean
我的理解:
InitFilter
是实际干活的InitChain
是个容器, 用来装InitFilter
, 并且依次执行所有filter;InitChainFactoryBean
是个工厂, 用来创造InitChain
的bean
权限刷新
自动刷新权限
服务注册后自动刷新权限流程:
admin服务:
PermissionInitFilter#doFilter PermissionRefreshService#innerRefresh v1/tool/permission/inner/fresh ACTUATOR_PERMISSION("/v2/actuator/permission", HttpMethod.GET, false, "获取服务权限信息"); //注意端口不是管理端口, 是服务端口;
iam服务:
ToolPermissionController#innerRefresh IDocumentServiceImpl#refreshPermissionAsync IDocumentServiceImpl#refreshPermission ParseServicePermissionImpl#parser List<Permission> permissions = this.permissionHandler.handle(serviceName, instance); AbstractPermissionHandler#handle ActuatorPermissionHandler#doHandle fetchPermissionDataByIp
手动刷新权限
开发管理 - 系统工具 - 刷新权限: /iam/v1/tool/permission/fresh
iam服务:
ToolPermissionController#refresh IDocumentServiceImpl#refreshPermission ParseServicePermissionImpl#parser AbstractPermissionHandler#handle ParseServicePermissionImpl#processPermissions
ParseService#parser
的javadoc:
解析权限步骤:
- 判断是否要跳过解析服务权限,默认跳过 register, gateway, oauth
- 调用服务接口 /v2/choerodon/api-docs 获取服务 swagger json 文档
- 从 json 中解析权限
- 如果权限编码重复,加上 HttpMethod 后缀
- 保存权限,编码存在则更新,不存在则新增
- 如果要清除过期权限,则清除过期权限
- 缓存权限到Redis,默认存储到 db4>gateway:permissions
实测: 手动刷新权限不会更新HADM_SWAGGER
表里的数据; 程序每次启动的时候会更新HADM_SWAGGER
并且刷新权限;
权限刷新报错: parse_permission_data.failure
症状: 【系统工具】-【刷新权限】报错:
hiam.error.parse_permission_data.failure
原因: iam刷新权限时获取的结果是乱码, 导致解析失败;
乱码原因: jhipster的prod模式开启了http响应压缩, 返回的数据被压缩, response header里包含: content-encoding: gzip
;
restTemplate没有兼容压缩的情况;
关闭压缩: server.compression.enabled: false
Using JHipster in production
路由刷新
路由配置
ChoerodonRouteData choerodonRouteData = new ChoerodonRouteData(); choerodonRouteData.setName(environment.getProperty("hzero.service.current.name", "demo")); choerodonRouteData.setPath(environment.getProperty("hzero.service.current.path", "/demo/**")); choerodonRouteData.setServiceId(environment.getProperty("hzero.service.current.service-name", "demo"));
- choerodonRouteData.name: 路由名称, gatewayRoute的标识,对应gatewayRoute的id字段
- choerodonRouteData.path: 路由的路径;
- choerodonRouteData.serviceId: 通过实测、查看代码, 业务服务的这个配置无效; 虽然无效, 但是也不能不设置, 否则程序启动报错, bean实例化失败;
admin刷新路由的时候, 会把路由配置里的serviceId设置为serviceName: ParseRouteServiceImpl#executeRefreshRoute data.setServiceId(serviceName);
如果开启了context-path, 路由配置需注意
//如果开启了context-path, 这里的路径必须和context-path保持一致 choerodonRouteData.setPath(environment.getProperty("hzero.service.current.path", "/demo-qxx/**")); //这里设置为false choerodonRouteData.setStripPrefix(false);
业务服务路由的name或path重复
新服务注册的路由如果和已有服务重复, 新服务会注册不上路由, 业务服务的日志里没有任何提示; admin服务里会info:
ParseRouteServiceImpl#executeRefreshRoute LOGGER.info("route conflict, try to modify it on the interface, cause: {}", cause.toString());
路由被占用, 服务路由注册失败, swagger里会看不到服务, 普通开发者很难排查问题;
最终采用的解决办法: 服务启动时路由注册成功才能启动(hzero原版检查健康状态为up就能启动)
手动刷新路由报错: http transport failed, ExceptionResponse: For input string: "80,80"
dev环境正常, prod环境访问服务时报错error.permission.routeNotFound
, 路由管理能看到路由, 手动刷新路由报错:
refresh service route error, serviceName=hw-platform, ex=fetch failed, instance: hw-platform, ex=http transport failed, ExceptionResponse: For input string: "80,80"
admin报错代码位置:
StringHttpTransporter#transport ExceptionResponse response = objectMapper.readValue(body, ExceptionResponse.class); if (response != null && response.getFailed()) { throw new RestClientException("http transport failed, ExceptionResponse: " + response.getMessage()); }
服务报错:
java.lang.NumberFormatException: For input string: "80,80" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:1.8.0_272] at java.lang.Integer.parseInt(Integer.java:580) ~[na:1.8.0_272] at java.lang.Integer.parseInt(Integer.java:615) ~[na:1.8.0_272] at ....swagger.controller.CustomController.componentsFrom(CustomController.java:145) ~[starter-core-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
代码位置:
...swagger.controller.CustomController#componentsFrom String port = request.getHeader("X-Forwarded-Port"); if (hasText(port)) { builder.port(Integer.parseInt(port)); }
报错原因: X-Forwarded-Port=80,80
;
修复方法: 加try..catch, 重置为-1;
这篇关于HZERO微服务平台10: 代码分析之admin服务刷新路由、权限、swagger的过程 .md的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-25Java编程面试题详解与解答
- 2024-12-25TS基础知识详解:初学者必看教程
- 2024-12-252024面试题解析与攻略:从零开始的面试准备指南
- 2024-12-25数据结构与算法学习:新手入门教程
- 2024-12-25初学者必备:订单系统资料详解与实操教程
- 2024-12-24内网穿透资料入门教程
- 2024-12-24微服务资料入门指南
- 2024-12-24微信支付系统资料入门教程
- 2024-12-24微信支付资料详解:新手入门指南
- 2024-12-24Hbase资料:新手入门教程