当前位置: 首页 > news >正文

重庆市建设工程信息网站诚信分软件编程培训学校排名

重庆市建设工程信息网站诚信分,软件编程培训学校排名,免费企业建站模板,Wordpress文章和tag标签sentinel集成网关支持restful接口进行url粒度的流量治理前言使用网关进行总体流量治理(sentinel版本:1.8.6)1、cloud gateway添加依赖:2、sentinel配置3、网关类型项目配置4、通过zk事件监听刷新上报api分组信息1、非网关项目上报api分组信息…

sentinel集成网关支持restful接口进行url粒度的流量治理

  • 前言
  • 使用网关进行总体流量治理(sentinel版本:1.8.6)
    • 1、cloud gateway添加依赖:
    • 2、sentinel配置
    • 3、网关类型项目配置
    • 4、通过zk事件监听刷新上报api分组信息
      • 1、非网关项目上报api分组信息
      • 2、网关添加监听事件
      • 3、网关监听事件处理
    • 5、sentinel控制台启动

前言

sentinel作为开源的微服务、流量治理组件,在对restful接口的支持上,在1.7之后才开始友好起来,对于带有@PathVariable的restful接口未作支持,在sentinel中/api/{id}这样的接口,其中/api/1与/api/2会被当做两个不同的接口处理,因此很难去做类似接口的流量治理,但在之后,sentinel团队已经提供了响应的csp扩展依赖,下文将会逐步讲述如何通过sentinel扩展来支持相应的服务流量治理

使用网关进行总体流量治理(sentinel版本:1.8.6)

这里选型为spring cloud gateway,而sentinel也对spring cloud gateway做了特殊照顾

1、cloud gateway添加依赖:

 <!-- alibaba封装的sentinel的starter --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>2021.1</version></dependency><!-- alibaba封装的sentinel支持网关的starter --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId><version>2021.1</version></dependency><!-- 此包即为sentinel提供的扩展支持restful接口的依赖 --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-spring-webmvc-adapter</artifactId><version>1.8.0</version></dependency>

上述需要重点关注的是sentinel-spring-webmvc-adapter包,此依赖是支持restful接口的关键,不需要我们自己改造。

2、sentinel配置

spring:cloud:sentinel:transport:#sentinel控制台地址dashboard: 1.1.1.1:8600#sentinel通信端口,默认为8179,被占用会继续扫描,一般固定起来port: 8700#项目所在服务器ipclient-ip: 2.2.2.2#心跳启动eager: true

client-ip在某些情况下不配置会出现sentinl控制台页面只有首页,服务一直注册不上去的情况,如果出现这种情况一定要配置上,如果没有这种情况,client-IP可以不配置,同时上述配置的这些ip端口都需要连通。

3、网关类型项目配置

/*** @classDesc:* @author: cyjer* @date: 2023/1/30 9:53*/
@SpringBootApplication
@EnableCaching
@Slf4j
public class SiriusApplication {public static void main(String[] args) {System.getProperties().setProperty("csp.sentinel.app.type", "1");SpringApplication.run(SiriusApplication.class, args);log.info("<<<<<<<<<<启动成功>>>>>>>>>>");}}

如果是网关类型的项目,需要配置csp.sentinel.app.type= 1,普通项目与网关项目,在控制台上所展示和可使用的功能是不同的

4、通过zk事件监听刷新上报api分组信息

通过将接口分组按照不同粒度,如controller粒度,和具体api接口粒度,通过zookeeper修改数据监听的方式,通过网关监听该事件,实现将api分组信息写入到sentinel中。

1、非网关项目上报api分组信息

/*** @classDesc: 扫描项目接口上报api* @author: cyjer* @date: 2023/2/10 13:46*/
@Configuration
@Slf4j
@Order(1)
@RequiredArgsConstructor
public class ApiDefinitionReporter implements BeanPostProcessor, CommandLineRunner, Constraint {private final List<ApiSiriusDefinition> apiSiriusDefinitionList = new ArrayList<>();private final GatewayServiceProperties gatewayServiceProperties;private final Environment environment;private final static char JTR = '/';private final static String PASS = "/**";private final static String APPLICATION_NAME = "spring.application.name";private final static String CONTEXT_PATH = "server.servlet.context-path";private final static List<String> PASS_LIST = Arrays.asList("swaggerWelcome", "basicErrorController", "swaggerConfigResource", "openApiResource");private final ZookeeperService zookeeperService;@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// url访问路径为:访问基地址basePath+classMappingPath+methodPathif (!gatewayServiceProperties.isAutoReportAndRegister() || PASS_LIST.contains(beanName)) {return bean;}Class<?> beanClass = bean.getClass();Class<?> targetClass = AopUtils.getTargetClass(bean);//判断类上有无controller注解 spring代理类需用spring的注解扫描工具类查找RestController restController = AnnotationUtils.findAnnotation(beanClass, RestController.class);Controller controller = AnnotationUtils.findAnnotation(beanClass, Controller.class);//没有注解直接跳过扫描if (null == controller && null == restController) {return bean;}String applicationName = this.getApplicationName();//项目访问基地址String basePath = this.getBasePath();//如果类上有controller注解再查找requestMapping注解RequestMapping requestMapping = AnnotationUtils.findAnnotation(beanClass, RequestMapping.class);String classMappingPath = this.getClassMappingPath(requestMapping);//按照controller分组上报if (StringUtils.isNotBlank(classMappingPath)) {String controllerGroupPath = basePath + classMappingPath + PASS;ApiSiriusDefinition controllerGroup = new ApiSiriusDefinition();controllerGroup.setGatewayId(gatewayServiceProperties.getGatewayId());controllerGroup.setResource("服务:" + applicationName + ",控制器:" + targetClass.getSimpleName() + ",路径:" + controllerGroupPath);controllerGroup.setUrlPath(controllerGroupPath);apiSiriusDefinitionList.add(controllerGroup);}//查找类中所有方法,进行遍历Method[] methods = targetClass.getMethods();for (Method method : methods) {//查找方法上RequestMapping注解String methodPath = "";String requestType = "";RequestMapping methodRequestMapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);if (methodRequestMapping != null) {String[] value = methodRequestMapping.value();RequestMethod[] requestMethods = methodRequestMapping.method();if (value.length == 0) {if (requestMethods.length == 0) {return bean;}RequestMethod requestMethod = requestMethods[0];requestType = requestMethod.name();if (requestMethod.equals(RequestMethod.POST)) {PostMapping postMapping = AnnotationUtils.findAnnotation(method, PostMapping.class);methodPath = this.joinMethodPath(postMapping.value());} else if (requestMethod.equals(RequestMethod.GET)) {GetMapping getMapping = AnnotationUtils.findAnnotation(method, GetMapping.class);methodPath = this.joinMethodPath(getMapping.value());} else if (requestMethod.equals(RequestMethod.DELETE)) {DeleteMapping deleteMapping = AnnotationUtils.findAnnotation(method, DeleteMapping.class);methodPath = this.joinMethodPath(deleteMapping.value());} else if (requestMethod.equals(RequestMethod.PATCH)) {PatchMapping patchMapping = AnnotationUtils.findAnnotation(method, PatchMapping.class);methodPath = this.joinMethodPath(patchMapping.value());} else if (requestMethod.equals(RequestMethod.PUT)) {PutMapping putMapping = AnnotationUtils.findAnnotation(method, PutMapping.class);methodPath = this.joinMethodPath(putMapping.value());}}ApiSiriusDefinition apiSiriusDefinition = new ApiSiriusDefinition();String urlPath = basePath + classMappingPath + methodPath;apiSiriusDefinition.setUrlPath(urlPath);apiSiriusDefinition.setRequestType(requestType);apiSiriusDefinition.setGatewayId(gatewayServiceProperties.getGatewayId());apiSiriusDefinition.setResource("服务:" + applicationName + ",请求类型:" + requestType + ",路径:" + urlPath);apiSiriusDefinitionList.add(apiSiriusDefinition);}}return bean;}private String joinMethodPath(String[] value) {if (value.length != 0) {String str = this.trimStrWith(value[0], JTR);return JTR + str;}return "";}private String getContextPath() {String contextPath = environment.getProperty(CONTEXT_PATH);contextPath = this.trimStrWith(contextPath, JTR);return StringUtils.isBlank(contextPath) ? "" : contextPath;}public String getApplicationName() {String applicationName = environment.getProperty(APPLICATION_NAME);applicationName = this.trimStrWith(applicationName, JTR);return StringUtils.isBlank(applicationName) ? "" : applicationName;}private String getBasePath() {String contextPath = this.getContextPath();String applicationName = this.getApplicationName();if (StringUtils.isBlank(contextPath)) {return JTR + applicationName;}return JTR + applicationName + JTR + contextPath;}private String getClassMappingPath(RequestMapping requestMapping) {if (null != requestMapping) {String requestMappingUrl = requestMapping.value().length == 0 ? "" : requestMapping.value()[0];requestMappingUrl = this.trimStrWith(requestMappingUrl, JTR);return JTR + requestMappingUrl;}return "";}public String trimStrWith(String str, char trimStr) {if (StringUtils.isBlank(str)) {return str;}int st = 0;int len = str.length();char[] val = str.toCharArray();while ((st < len) && (val[st] <= trimStr)) {st++;}while ((st < len) && (val[len - 1] <= trimStr)) {len--;}return ((st > 0) || (len < str.length())) ? str.substring(st, len) : str;}@Overridepublic void run(String... args) {if (StringUtils.isBlank(this.getApplicationName())) {throw new RuntimeException(APPLICATION_NAME + " should not be null");}if (!apiSiriusDefinitionList.isEmpty()) {log.info("<<<<< start to report api information to api governance platform >>>>>");try {zookeeperService.create(API_DEFINITION + SPLIT + getApplicationName(), JSONArray.toJSONString(apiSiriusDefinitionList));zookeeperService.update(API_DEFINITION + SPLIT + getApplicationName(), JSONArray.toJSONString(apiSiriusDefinitionList));} catch (Exception e) {log.error("reported api information failed,stack info:", e);}log.info("<<<<< successfully reported api information >>>>>");}}}

通过扫描项目下的controller和相应的mapping注解中的属性拼接出url来,通过zk来更新节点数据

2、网关添加监听事件

zk操作查看另一篇文章zookeeper相关操作

/*** @classDesc: 网关核心应用* @author: cyjer* @date: 2023/1/30 9:53*/
@Component
@Slf4j
@RequiredArgsConstructor
public class GatewayApplication implements ApplicationListener<ContextRefreshedEvent> {private final GatewayServiceProperties properties;private final ApiDefinitionService apiDefinitionService;private final ZookeeperService zookeeperService;private final ApiGroupProcesser apiGroupProcesser;@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {//拉取api governance platform 信息apiDefinitionService.refreshApiGovernanceInfo(properties.getGatewayId());log.info("<<<<<<<<<<刷新api分组信息完成>>>>>>>>>>");zookeeperService.create(Constraint.API_DEFINITION, "init");zookeeperService.addWatchChildListener(Constraint.API_DEFINITION, apiGroupProcesser);log.info("<<<<<<<<<<api上报监听器配置完成>>>>>>>>>>");}
}

通过事件处理,首先启动时刷新api信息,同时尝试初始化zk节点,然后注册监听watch。

3、网关监听事件处理

/*** @classDesc: api分组上报* @author: cyjer* @date: 2023/2/10 11:13*/
@Slf4j
@Component
public class ApiGroupProcesser extends AbstractChildListenerProcess implements ApiDefinitionConstraint {@Resourceprivate RedisTemplate<String, Object> redisTemplate;@Resourceprivate GatewayServiceProperties gatewayServiceProperties;@Overridepublic void process(CuratorFramework curatorFramework, PathChildrenCacheEvent cacheEvent) {ChildData data = cacheEvent.getData();if (Objects.nonNull(data) && cacheEvent.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)) {log.info("<<<<<<<<<<上报api分组到sentinel>>>>>>>>>>");String path = data.getPath();String content = new String(data.getData(), StandardCharsets.UTF_8);Set<ApiDefinition> definitions = GatewayApiDefinitionManager.getApiDefinitions();List<ApiSiriusDefinition> list = JSONArray.parseArray(content, ApiSiriusDefinition.class);for (ApiSiriusDefinition apiGroup : list) {ApiDefinition api = new ApiDefinition(apiGroup.getResource()).setPredicateItems(new HashSet<ApiPredicateItem>() {{add(new ApiPathPredicateItem().setPattern(apiGroup.getUrlPath()).setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));}});definitions.add(api);}GatewayApiDefinitionManager.loadApiDefinitions(definitions);redisTemplate.opsForHash().put(API_INFO_REDIS_PREFIX + gatewayServiceProperties.getGatewayId(), path, JSONArray.toJSONString(list));log.info("<<<<<<<<<<上报api分组到sentinel成功>>>>>>>>>>");}}
}

5、sentinel控制台启动

java -Dserver.port=8600 -Dcsp.sentinel.dashboard.server=localhost:8600 -Dproject.name=sentinel-dashboard -Xms512m -Xmx512m -Xmn256m -XX:MaxMetaspaceSize=100m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/oom/log -Dfile.encoding=UTF-8 -XX:+UseG1GC -jar sentinel-dashboard-1.8.6.jar

打开sentinel控制台,请求几次接口后
在这里插入图片描述

可以看到相应的api分组信息和url路径匹配都已加载,在进行流量治理的时候就可以支持restful接口和controller粒度的治理了

http://www.khdw.cn/news/17812.html

相关文章:

  • 景德镇做网站百度问答官网
  • 长沙营销型网站建设正规接单赚佣金的平台
  • 企业培训网站模板抖音搜索排名
  • 成品网站是什么漂亮的网页设计
  • 外贸网站制作要求泽成seo网站排名
  • 苏宁网站开发人员微信朋友圈广告推广代理
  • 邯郸做wap网站微博付费推广有用吗
  • 长丰县建设委员会网站是哪个交易链接
  • 做自己的视频网站响应式网站模板的特点
  • 怎么开一家客服外包公司优化搜索关键词
  • 云南手机网站制作营销软文广告
  • 做网站项目后台的百度咨询
  • 建设一个网站可以采用哪几种方案低价刷赞网站推广
  • 做网站哪里买空间好企业网站seo诊断报告
  • wordpress文章自动内链厦门百度整站优化服务
  • 最专业的网站建设价格数字营销平台有哪些
  • iis 网站文件被占用郑州seo价格
  • dedecms wap网站模板下载百度上传自己个人简介
  • 旅行社网站建设的目的网站网络推广公司
  • 做网站手机端不做PC可以吗营销助手
  • 动画视频模板网站网站权重查询
  • 凡科建站公司昆明seo技术培训
  • 网站设计教程dreamweaver竞价托管推广哪家好
  • 谁有可以用的网站网络营销与传统营销的区别
  • 哪里可以上传自己的php网站sem运营是什么意思
  • 国家对地理信息网站建设的重视谷歌推广效果好吗
  • 商业网站建设试题广告优化师工资一般多少
  • 做移动网站开发迅雷磁力链bt磁力天堂
  • 邹城网站建设v556宁波seo公司网站推广
  • 嘉兴城乡建设局门户网站网站搭建免费