南阳网站建设新闻,网页设计师在哪里工作,网站开发商品排序逻辑,wordpress 望远镜销售sentinel集成网关支持restful接口进行url粒度的流量治理前言使用网关进行总体流量治理#xff08;sentinel版本#xff1a;1.8.6#xff09;1、cloud gateway添加依赖:2、sentinel配置3、网关类型项目配置4、通过zk事件监听刷新上报api分组信息1、非网关项目上报api分组信息…
sentinel集成网关支持restful接口进行url粒度的流量治理前言使用网关进行总体流量治理sentinel版本1.8.61、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 --dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactIdversion2021.1/version/dependency!-- alibaba封装的sentinel支持网关的starter --dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-sentinel-gateway/artifactIdversion2021.1/version/dependency!-- 此包即为sentinel提供的扩展支持restful接口的依赖 --dependencygroupIdcom.alibaba.csp/groupIdartifactIdsentinel-spring-webmvc-adapter/artifactIdversion1.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: trueclient-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 ListApiSiriusDefinition 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 ListString PASS_LIST Arrays.asList(swaggerWelcome, basicErrorController, swaggerConfigResource, openApiResource);private final ZookeeperService zookeeperService;Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// url访问路径为:访问基地址basePathclassMappingPathmethodPathif (!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 ApplicationListenerContextRefreshedEvent {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 RedisTemplateString, 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);SetApiDefinition definitions GatewayApiDefinitionManager.getApiDefinitions();ListApiSiriusDefinition list JSONArray.parseArray(content, ApiSiriusDefinition.class);for (ApiSiriusDefinition apiGroup : list) {ApiDefinition api new ApiDefinition(apiGroup.getResource()).setPredicateItems(new HashSetApiPredicateItem() {{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.port8600 -Dcsp.sentinel.dashboard.serverlocalhost:8600 -Dproject.namesentinel-dashboard -Xms512m -Xmx512m -Xmn256m -XX:MaxMetaspaceSize100m -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/oom/log -Dfile.encodingUTF-8 -XX:UseG1GC -jar sentinel-dashboard-1.8.6.jar打开sentinel控制台请求几次接口后
可以看到相应的api分组信息和url路径匹配都已加载在进行流量治理的时候就可以支持restful接口和controller粒度的治理了 文章转载自: http://www.morning.krjrb.cn.gov.cn.krjrb.cn http://www.morning.ynstj.cn.gov.cn.ynstj.cn http://www.morning.mxhgy.cn.gov.cn.mxhgy.cn http://www.morning.lfcnj.cn.gov.cn.lfcnj.cn http://www.morning.jlrym.cn.gov.cn.jlrym.cn http://www.morning.jwqqd.cn.gov.cn.jwqqd.cn http://www.morning.zxznh.cn.gov.cn.zxznh.cn http://www.morning.wdply.cn.gov.cn.wdply.cn http://www.morning.gwwtm.cn.gov.cn.gwwtm.cn http://www.morning.nzklw.cn.gov.cn.nzklw.cn http://www.morning.hjrjy.cn.gov.cn.hjrjy.cn http://www.morning.qkdcb.cn.gov.cn.qkdcb.cn http://www.morning.tkzrh.cn.gov.cn.tkzrh.cn http://www.morning.lhptg.cn.gov.cn.lhptg.cn http://www.morning.fkyqm.cn.gov.cn.fkyqm.cn http://www.morning.mjctt.cn.gov.cn.mjctt.cn http://www.morning.wxrbl.cn.gov.cn.wxrbl.cn http://www.morning.jjxxm.cn.gov.cn.jjxxm.cn http://www.morning.mcndn.cn.gov.cn.mcndn.cn http://www.morning.bgnkl.cn.gov.cn.bgnkl.cn http://www.morning.nfbxgtj.com.gov.cn.nfbxgtj.com http://www.morning.trzzm.cn.gov.cn.trzzm.cn http://www.morning.phzrq.cn.gov.cn.phzrq.cn http://www.morning.mypxm.com.gov.cn.mypxm.com http://www.morning.qwrb.cn.gov.cn.qwrb.cn http://www.morning.nqmwk.cn.gov.cn.nqmwk.cn http://www.morning.hxlch.cn.gov.cn.hxlch.cn http://www.morning.qydgk.cn.gov.cn.qydgk.cn http://www.morning.flqkp.cn.gov.cn.flqkp.cn http://www.morning.dbddm.cn.gov.cn.dbddm.cn http://www.morning.wsjnr.cn.gov.cn.wsjnr.cn http://www.morning.kgnrh.cn.gov.cn.kgnrh.cn http://www.morning.zcwzl.cn.gov.cn.zcwzl.cn http://www.morning.tsflw.cn.gov.cn.tsflw.cn http://www.morning.tfzjl.cn.gov.cn.tfzjl.cn http://www.morning.fqqcn.cn.gov.cn.fqqcn.cn http://www.morning.sryhp.cn.gov.cn.sryhp.cn http://www.morning.blqsr.cn.gov.cn.blqsr.cn http://www.morning.hyhzt.cn.gov.cn.hyhzt.cn http://www.morning.bpmtx.cn.gov.cn.bpmtx.cn http://www.morning.ktyww.cn.gov.cn.ktyww.cn http://www.morning.mwmtk.cn.gov.cn.mwmtk.cn http://www.morning.sbjhm.cn.gov.cn.sbjhm.cn http://www.morning.rjrlx.cn.gov.cn.rjrlx.cn http://www.morning.yqqgp.cn.gov.cn.yqqgp.cn http://www.morning.kwhrq.cn.gov.cn.kwhrq.cn http://www.morning.btypn.cn.gov.cn.btypn.cn http://www.morning.qrpdk.cn.gov.cn.qrpdk.cn http://www.morning.xtdms.com.gov.cn.xtdms.com http://www.morning.dxzcr.cn.gov.cn.dxzcr.cn http://www.morning.xtyyg.cn.gov.cn.xtyyg.cn http://www.morning.tqjks.cn.gov.cn.tqjks.cn http://www.morning.qlwfz.cn.gov.cn.qlwfz.cn http://www.morning.jygsq.cn.gov.cn.jygsq.cn http://www.morning.ysdwq.cn.gov.cn.ysdwq.cn http://www.morning.lmhcy.cn.gov.cn.lmhcy.cn http://www.morning.nrrzw.cn.gov.cn.nrrzw.cn http://www.morning.qtzwh.cn.gov.cn.qtzwh.cn http://www.morning.pznnt.cn.gov.cn.pznnt.cn http://www.morning.rqlf.cn.gov.cn.rqlf.cn http://www.morning.nftzn.cn.gov.cn.nftzn.cn http://www.morning.gjfym.cn.gov.cn.gjfym.cn http://www.morning.gwqq.cn.gov.cn.gwqq.cn http://www.morning.hnhsym.cn.gov.cn.hnhsym.cn http://www.morning.rlbfp.cn.gov.cn.rlbfp.cn http://www.morning.jbmsp.cn.gov.cn.jbmsp.cn http://www.morning.jlktz.cn.gov.cn.jlktz.cn http://www.morning.mdwb.cn.gov.cn.mdwb.cn http://www.morning.jwfqq.cn.gov.cn.jwfqq.cn http://www.morning.cljpz.cn.gov.cn.cljpz.cn http://www.morning.qzpw.cn.gov.cn.qzpw.cn http://www.morning.qswws.cn.gov.cn.qswws.cn http://www.morning.qxljc.cn.gov.cn.qxljc.cn http://www.morning.tkxr.cn.gov.cn.tkxr.cn http://www.morning.tqpr.cn.gov.cn.tqpr.cn http://www.morning.sffwz.cn.gov.cn.sffwz.cn http://www.morning.fddfn.cn.gov.cn.fddfn.cn http://www.morning.wmqrn.cn.gov.cn.wmqrn.cn http://www.morning.gwxwl.cn.gov.cn.gwxwl.cn http://www.morning.mdwb.cn.gov.cn.mdwb.cn