├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── maven.yml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── pom.xml ├── sds-admin ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── didiglobal │ │ │ └── sds │ │ │ └── admin │ │ │ ├── SdsAdminApplication.java │ │ │ ├── aop │ │ │ └── SdsAspectAop.java │ │ │ ├── conditional │ │ │ ├── MultConditionalOnProperty.java │ │ │ └── MultOnPropertyCondition.java │ │ │ ├── constants │ │ │ └── SdsCode.java │ │ │ ├── controller │ │ │ ├── AppGroupController.java │ │ │ ├── AppInfoController.java │ │ │ ├── DashboardController.java │ │ │ ├── HeartbeatController.java │ │ │ ├── PointDictController.java │ │ │ ├── PointReturnValueController.java │ │ │ ├── PointStrategyController.java │ │ │ ├── SdsSchemeController.java │ │ │ ├── bean │ │ │ │ ├── DashboardPoint.java │ │ │ │ ├── PageInfo.java │ │ │ │ └── PointDictVO.java │ │ │ ├── request │ │ │ │ ├── AbstractRequest.java │ │ │ │ ├── AppGroupRequest.java │ │ │ │ ├── AppInfoRequest.java │ │ │ │ ├── DashboardPointRequest.java │ │ │ │ ├── DashboardRequest.java │ │ │ │ ├── HeartbeatQueryRequest.java │ │ │ │ ├── PointDictRequest.java │ │ │ │ ├── PointReturnValueRequest.java │ │ │ │ ├── PointStrategyRequest.java │ │ │ │ └── SdsSchemeRequest.java │ │ │ └── response │ │ │ │ ├── DashboardResponse.java │ │ │ │ └── SdsResponse.java │ │ │ ├── dao │ │ │ ├── AppGroupDao.java │ │ │ ├── AppInfoDao.java │ │ │ ├── HeartbeatDao.java │ │ │ ├── PointDictDao.java │ │ │ ├── PointReturnValueDao.java │ │ │ ├── PointStrategyDao.java │ │ │ ├── SdsSchemeDao.java │ │ │ ├── UserPrivilegeDao.java │ │ │ ├── bean │ │ │ │ ├── AppGroupDO.java │ │ │ │ ├── AppInfoDO.java │ │ │ │ ├── HeartbeatDO.java │ │ │ │ ├── PointDictDO.java │ │ │ │ ├── PointReturnValueDO.java │ │ │ │ ├── PointStrategyDO.java │ │ │ │ ├── SdsSchemeDO.java │ │ │ │ └── UserPrivilege.java │ │ │ └── impl │ │ │ │ └── InfluxHeartbeatDaoImpl.java │ │ │ ├── exception │ │ │ └── SdsBizException.java │ │ │ ├── remote │ │ │ └── SdsRestTemplate.java │ │ │ ├── service │ │ │ ├── DashboardService.java │ │ │ ├── HeartbeatService.java │ │ │ ├── PointDictService.java │ │ │ ├── bean │ │ │ │ ├── DashboardMainBO.java │ │ │ │ ├── HeartbeatBO.java │ │ │ │ └── HeartbeatShowBO.java │ │ │ └── impl │ │ │ │ ├── DashboardServiceImpl.java │ │ │ │ ├── HeartbeatServiceImpl.java │ │ │ │ └── PointDictServiceImpl.java │ │ │ └── util │ │ │ ├── BloomFileter.java │ │ │ ├── FastBeanUtil.java │ │ │ ├── HttpResponse.java │ │ │ └── StringCheck.java │ └── resources │ │ ├── config │ │ ├── application-dev.properties │ │ ├── application-docker.properties │ │ ├── application-online.properties │ │ ├── application.properties │ │ ├── log4j2.xml │ │ └── logback.xml │ │ └── db │ │ ├── h2.sql │ │ └── mysql.sql │ └── test │ ├── java │ └── com │ │ └── didiglobal │ │ └── sds │ │ └── admin │ │ └── test │ │ ├── SdsAdminApplicationTest.java │ │ ├── controller │ │ ├── AppGroupControllerTest.java │ │ ├── AppInfoControllerTest.java │ │ ├── PointDictControllerTest.java │ │ ├── SdsSchemeControllerTest.java │ │ └── StrategyPointControllerTest.java │ │ ├── dao │ │ ├── AppGroupDaoTest.java │ │ ├── AppInfoDaoTest.java │ │ ├── HeartbeatDaoTest.java │ │ ├── InfluxHeartbeatDaoImplTest.java │ │ ├── PointDictDaoTest.java │ │ ├── PointReturnValueDaoTest.java │ │ ├── PointStrategyDaoTest.java │ │ └── SdsSchemeDaoTest.java │ │ └── service │ │ └── PointDictServiceTest.java │ └── resources │ └── config │ ├── application.properties │ └── logback.xml ├── sds-bootstrap ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── didiglobal │ └── sds │ └── bootstrap │ ├── SdsBootStrap.java │ └── transformer │ └── SdsClassFileTransformer.java ├── sds-client ├── .gitignore ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── didiglobal │ │ └── sds │ │ └── client │ │ ├── AbstractSdsClient.java │ │ ├── CommonSdsClient.java │ │ ├── SdsClient.java │ │ ├── SdsClientFactory.java │ │ ├── annotation │ │ ├── SdsDowngradeMethod.java │ │ └── SdsStrategyExecutor.java │ │ ├── bean │ │ ├── CheckData.java │ │ ├── HeartBeatResponse.java │ │ ├── HeartbeatRequest.java │ │ ├── SdsClassDefine.java │ │ ├── SdsCycleInfo.java │ │ ├── SdsStrategy.java │ │ └── VisitWrapperValue.java │ │ ├── config │ │ ├── SdsDowngradeActionNotify.java │ │ ├── SdsPointReturnValueConfig.java │ │ └── SdsPointStrategyConfig.java │ │ ├── contant │ │ ├── BizConstant.java │ │ └── ExceptionCode.java │ │ ├── counter │ │ ├── AbstractCycleData.java │ │ ├── ConcurrentData.java │ │ ├── PowerfulCycleTimeCounter.java │ │ ├── SlidingWindowData.java │ │ └── TokenBucketData.java │ │ ├── enums │ │ └── DowngradeActionType.java │ │ ├── exception │ │ └── SdsException.java │ │ ├── listener │ │ └── DowngradeActionListener.java │ │ ├── log │ │ ├── SdsLoggerConstants.java │ │ └── SdsLoggerFactory.java │ │ ├── service │ │ ├── CycleDataService.java │ │ ├── SdsDowngradeDelayService.java │ │ ├── SdsDowngradeExceptionService.java │ │ ├── SdsDowngradeReturnValueService.java │ │ ├── SdsHeartBeatService.java │ │ ├── SdsPowerfulCounterService.java │ │ ├── SdsStrategyService.java │ │ └── SdsTimeoutService.java │ │ ├── strategy │ │ ├── DefaultStrategyExecutorBuilder.java │ │ ├── StrategyExecutorBuilder.java │ │ └── executor │ │ │ ├── AbstractStrategyExecutor.java │ │ │ ├── ConcurrentStrategyExecutor.java │ │ │ ├── ExceptionRateStrategyExecutor.java │ │ │ ├── ExceptionStrategyExecutor.java │ │ │ ├── TimeoutStrategyExecutor.java │ │ │ ├── TokenBucketStrategyExecutor.java │ │ │ └── VisitStrategyExecutor.java │ │ └── util │ │ ├── AssertUtil.java │ │ ├── ClassTool.java │ │ ├── DateUtils.java │ │ ├── HttpUtils.java │ │ ├── IpUtils.java │ │ ├── JsonUtils.java │ │ ├── ListUtils.java │ │ ├── ResourceTool.java │ │ ├── SdsClassReader.java │ │ ├── StringUtils.java │ │ └── TimeStatisticsUtil.java │ └── test │ ├── java │ └── com │ │ └── didiglobal │ │ └── sds │ │ └── client │ │ └── test │ │ ├── AbstractDowngradeTest.java │ │ ├── ConcurrentDowngradeTest.java │ │ ├── CustomStrategyExecutorBuilder.java │ │ ├── CustomStrategyExecutorBuilder2.java │ │ ├── CustomStrategyExecutorBuilderTest.java │ │ ├── ExceptionDowngradeTest.java │ │ ├── ExceptionRateDowngradeTest.java │ │ ├── TimeoutDowngradeTest.java │ │ ├── TokenBucketDowngradeTest.java │ │ └── VisitDowngradeTest.java │ └── resources │ ├── META-INF │ └── services │ │ └── com.didiglobal.sds.client.strategy.StrategyExecutorBuilder │ └── log4j.xml ├── sds-easy ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── didiglobal │ │ └── sds │ │ └── easy │ │ ├── BizFunction.java │ │ ├── BizFunctionWithoutReturn.java │ │ ├── DowngradeFunction.java │ │ ├── DowngradeFunctionWithoutReturn.java │ │ └── SdsEasyUtil.java │ └── test │ ├── java │ └── com │ │ └── didiglobal │ │ └── sds │ │ └── easy │ │ └── test │ │ └── SdsEasyUtilTest.java │ └── resources │ └── log4j.xml ├── sds-example ├── pom.xml ├── sds-apache-dubbo-example │ ├── README.md │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── didiglobal │ │ │ │ └── sds │ │ │ │ └── example │ │ │ │ ├── DemoServiceApplication.java │ │ │ │ ├── api │ │ │ │ └── HelloService.java │ │ │ │ └── service │ │ │ │ └── HelloServiceImpl.java │ │ └── resources │ │ │ ├── application-consumer.yml │ │ │ ├── application-provider.yml │ │ │ └── application.yml │ │ └── test │ │ └── java │ │ └── com │ │ └── didiglobal │ │ └── sds │ │ └── example │ │ └── DemoServiceConsumerApplicationTests.java └── sds-client-example │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── com │ │ └── didiglobal │ │ └── sds │ │ └── example │ │ ├── chapter1 │ │ ├── UseOriginApi.java │ │ └── UseOriginApiAndSdsAdmin.java │ │ ├── chapter2 │ │ └── UserSdsEasyAndSdsAdmin.java │ │ ├── chapter3 │ │ ├── OrderManageService.java │ │ └── UseAnnotationByAspectj.java │ │ └── chapter4 │ │ ├── OrderManageService.java │ │ ├── SdsConfiguration.java │ │ ├── SpringBoootWithSds.java │ │ └── SpringBoootWithSdsTest.java │ └── resources │ ├── application-dev.properties │ ├── application.properties │ └── chapter3-spring.xml ├── sds-extension ├── pom.xml ├── sds-apache-dubbo │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── didiglobal │ │ │ └── sds │ │ │ └── extension │ │ │ └── dubbo │ │ │ └── filter │ │ │ └── SdsApacheDubboFilter.java │ │ └── resources │ │ └── META-INF │ │ └── dubbo │ │ └── org.apache.dubbo.rpc.Filter ├── sds-aspectj │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── didiglobal │ │ └── sds │ │ └── aspectj │ │ └── SdsPointAspect.java ├── sds-dubbo │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── didiglobal │ │ │ └── sds │ │ │ └── extension │ │ │ └── dubbo │ │ │ └── filter │ │ │ └── SdsDubboFilter.java │ │ └── resources │ │ └── META-INF │ │ └── dubbo │ │ └── com.alibaba.dubbo.rpc.Filter ├── sds-okhttp │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── didiglobal │ │ └── sds │ │ └── extension │ │ └── okhttp │ │ └── SdsOkHttpInterceptor.java └── sds-spring-boot │ ├── pom.xml │ ├── sds-spring-boot-autoconfigure │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── didiglobal │ │ │ └── sds │ │ │ └── extension │ │ │ └── spring │ │ │ └── boot │ │ │ └── autoconfigure │ │ │ ├── SdsAutoConfiguration.java │ │ │ └── SdsProperties.java │ │ └── resources │ │ └── META-INF │ │ ├── spring-configuration-metadata.json │ │ └── spring.factories │ └── sds-spring-boot-starter │ └── pom.xml └── sds-front ├── .browserslistrc ├── .eslintrc.js ├── README.md ├── babel.config.js ├── build.sh ├── package.json ├── pom.xml ├── postcss.config.js ├── public ├── css │ └── font_848689_t1i7vl2sllq.css ├── imgs │ ├── kd09dBTlVw5uaosvhLS.png │ └── sds2.0.png ├── index.html └── js │ └── jquery.min.js ├── src ├── App.vue ├── api │ ├── api.js │ ├── common.js │ └── login.js ├── assets │ ├── css │ │ └── global.css │ └── img │ │ ├── SDS2.0-dev.png │ │ ├── SDS2.0-online.png │ │ ├── SDS2.0-pre.png │ │ └── logo-single.png ├── components │ ├── common │ │ ├── aside │ │ │ ├── aside.scss │ │ │ └── aside.vue │ │ ├── building │ │ │ ├── building.scss │ │ │ └── building.vue │ │ ├── content │ │ │ ├── content.scss │ │ │ └── content.vue │ │ ├── footer │ │ │ ├── footer.scss │ │ │ └── footer.vue │ │ └── header │ │ │ ├── header.scss │ │ │ └── header.vue │ └── home │ │ ├── appList │ │ ├── appList.scss │ │ └── appList.vue │ │ ├── echartDemo │ │ ├── echartDemo.scss │ │ └── echartDemo.vue │ │ └── monitor │ │ └── MonitorChart.vue ├── main.js ├── router.js ├── store │ ├── index.js │ └── modules │ │ └── user.js ├── utils │ ├── fetch.js │ ├── timeFormat.js │ └── utils.js └── views │ ├── About.vue │ ├── ApplicationGroup.vue │ ├── ApplyName.vue │ ├── DemotePoint.vue │ ├── DemotePointResponse.vue │ ├── DowngradeChart.vue │ ├── DowngradeMonitor.vue │ ├── SdsScheme.vue │ └── SettingUp.vue ├── tests └── unit │ ├── .eslintrc.js │ └── example.spec.js └── vue.config.js /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Java CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Set up JDK 1.8 13 | uses: actions/setup-java@v1 14 | with: 15 | java-version: 1.8 16 | - name: Build with Maven 17 | run: mvn -B package --file pom.xml 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #.gitignore for java 2 | *.class 3 | 4 | # Package Files # 5 | *.jar 6 | *.war 7 | *.ear 8 | **/target/ 9 | 10 | # logs 11 | /stacktrace.log 12 | /test/reports 13 | /logs 14 | *.log 15 | *.log.* 16 | 17 | ## .gitignore for intellij 18 | *.iml 19 | *.ipr 20 | *.iws 21 | .idea/ 22 | 23 | ## .gitignore for eclipse 24 | *.pydevproject 25 | .project 26 | .metadata 27 | bin/** 28 | tmp/** 29 | tmp/**/* 30 | *.tmp 31 | *.bak 32 | *.swp 33 | *~.nib 34 | .classpath 35 | .loadpath 36 | 37 | ## .gitignore for node 38 | sds-front/package-lock.json 39 | 40 | .DS_Store 41 | node_modules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: false # faster builds 3 | 4 | jdk: 5 | - openjdk8 6 | 7 | cache: 8 | directories: 9 | - $HOME/.m2 10 | 11 | install: true 12 | 13 | script: 14 | - mvn clean install -P 15 | 16 | after_success: 17 | - bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guideline 2 | 3 | Thanks for considering to contribute this project. All issues and pull requests are highly appreciated. 4 | 5 | ## Pull Requests 6 | 7 | Before sending pull request to this project, please read and follow guidelines below. 8 | 9 | 1. Branch: We only accept pull request on `master` branch. 10 | 2. Coding style: Follow the coding style used in sds. 11 | 3. Commit message: Use English and be aware of your spell. 12 | 4. Test: Make sure to test your code. 13 | 14 | Add device mode, API version, related log, screenshots and other related information in your pull request if possible. 15 | 16 | NOTE: We assume all your contribution can be licensed under the [Apache License 2.0](https://github.com/didi/sds/blob/master/LICENSE). 17 | 18 | ## Issues 19 | 20 | We love clearly described issues. :) 21 | 22 | Following information can help us to resolve the issue faster. 23 | 24 | * Device mode and hardware information. 25 | * API version. 26 | * Logs. 27 | * Screenshots. 28 | * Steps to reproduce the issue. 29 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/SdsAdminApplication.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SdsAdminApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SdsAdminApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/conditional/MultConditionalOnProperty.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.conditional; 2 | 3 | import org.springframework.context.annotation.Conditional; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * @Description: 相比ConditionalOnProperty支持多个条件的判断 12 | * @Author: manzhizhen 13 | * @Date: Create in 2019-09-15 13:42 14 | */ 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target({ElementType.TYPE, ElementType.METHOD}) 17 | @Conditional(MultOnPropertyCondition.class) 18 | public @interface MultConditionalOnProperty { 19 | 20 | String value() default ""; 21 | 22 | String name() default ""; 23 | 24 | String[] havingValue() default {}; 25 | } 26 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/conditional/MultOnPropertyCondition.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.conditional; 2 | 3 | import com.didiglobal.sds.client.util.StringUtils; 4 | import org.springframework.boot.autoconfigure.condition.ConditionOutcome; 5 | import org.springframework.boot.autoconfigure.condition.SpringBootCondition; 6 | import org.springframework.context.ConfigurableApplicationContext; 7 | import org.springframework.context.annotation.ConditionContext; 8 | import org.springframework.core.type.AnnotatedTypeMetadata; 9 | 10 | import java.util.Map; 11 | 12 | /** 13 | * @Description: 14 | * @Author: manzhizhen 15 | * @Date: Create in 2019-09-15 13:45 16 | */ 17 | public class MultOnPropertyCondition extends SpringBootCondition { 18 | 19 | @Override 20 | public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { 21 | Map annotationAttributes = metadata.getAnnotationAttributes(MultConditionalOnProperty. 22 | class.getName()); 23 | String propertyName = (String) annotationAttributes.get("name"); 24 | if (StringUtils.isBlank(propertyName)) { 25 | propertyName = (String) annotationAttributes.get("value"); 26 | } 27 | 28 | if (StringUtils.isBlank(propertyName)) { 29 | return new ConditionOutcome(false, "没发现配置name或value"); 30 | } 31 | 32 | String[] values = (String[]) annotationAttributes.get("havingValue"); 33 | if (values.length == 0) { 34 | return new ConditionOutcome(false, "没发现配置havingValue"); 35 | } 36 | 37 | String propertyValue = context.getEnvironment().getProperty(propertyName); 38 | if (StringUtils.isBlank(propertyValue)) { 39 | propertyValue = ((ConfigurableApplicationContext) context.getResourceLoader()).getEnvironment(). 40 | getProperty(propertyName); 41 | 42 | if (StringUtils.isBlank(propertyValue)) { 43 | return new ConditionOutcome(false, "没发现配置" + propertyName); 44 | } 45 | } 46 | 47 | /** 48 | * 相当于或的关系,只要有一个能匹配就算成功 49 | */ 50 | for (String havingValue : values) { 51 | if (propertyValue.equalsIgnoreCase(havingValue)) { 52 | return new ConditionOutcome(true, "匹配成功"); 53 | } 54 | } 55 | 56 | return new ConditionOutcome(false, "匹配失败"); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/constants/SdsCode.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.constants; 2 | 3 | /** 4 | * Sds错误码枚举 5 | */ 6 | public enum SdsCode { 7 | 8 | SUCCESS(200, "成功"), 9 | 10 | PARAM_ERROR(1001, "参数错误"), 11 | 12 | SYSTEM_ERROR(1002, "系统错误"), 13 | 14 | DATA_CHECK_FAIL(1003, "数据校验失败,请检查数据完整性"), 15 | 16 | UNIQUE_KEY_IS_EXISTS(1004, "唯一约束校验失败,数据已经存在!"), 17 | 18 | DATA_ID_NOT_EXISTS(1005, "数据ID不存在!"), 19 | 20 | RATE_RANGE_CHECK_FAIL(1006, "降级比例取值范围是[0-100]!"), 21 | 22 | MODULE_CAN_NOT_DELETE(1007, "该模块下存在降级点,无法删除!"); 23 | 24 | /** 25 | * 内部唯一标识 26 | */ 27 | private final Integer code; 28 | /** 29 | * 信息 30 | */ 31 | private final String msg; 32 | 33 | SdsCode(Integer code, String msg) { 34 | this.code = code; 35 | this.msg = msg; 36 | } 37 | 38 | /** 39 | * 返回错误码的code 40 | * @return 错误码的code 41 | */ 42 | public Integer getCode() { 43 | return code; 44 | } 45 | 46 | /** 47 | * 返回错误码的描述 48 | * @return 错误码描述 49 | */ 50 | public String getMsg() { 51 | return msg; 52 | } 53 | 54 | public static SdsCode valueOfCode(Integer code) { 55 | if (code == null) { 56 | return null; 57 | } 58 | for (SdsCode e : values()) { 59 | if (e.getCode().equals(code)) { 60 | return e; 61 | } 62 | } 63 | return null; 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/PointDictController.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller; 2 | 3 | import com.didiglobal.sds.client.util.StringUtils; 4 | import com.didiglobal.sds.admin.constants.SdsCode; 5 | import com.didiglobal.sds.admin.controller.request.PointDictRequest; 6 | import com.didiglobal.sds.admin.controller.response.SdsResponse; 7 | import com.didiglobal.sds.admin.dao.bean.PointDictDO; 8 | import com.didiglobal.sds.admin.service.PointDictService; 9 | import com.google.common.collect.Lists; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestMethod; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * Created by tianyulei on 2019/8/11 20 | **/ 21 | @RestController 22 | @RequestMapping(value = "/sds/pointdict/", method = RequestMethod.POST) 23 | public class PointDictController { 24 | 25 | @Autowired 26 | private PointDictService pointDictService; 27 | 28 | @RequestMapping(value = "querylist") 29 | public SdsResponse> queryPointDictList(@RequestBody PointDictRequest request) { 30 | if (request == null) { 31 | return new SdsResponse(SdsCode.PARAM_ERROR.getCode(), "请求参数错误,请联系程序猿"); 32 | } 33 | 34 | if (StringUtils.isBlank(request.getAppGroupName())) { 35 | return new SdsResponse(SdsCode.PARAM_ERROR.getCode(), "应用组名称不能为空"); 36 | } 37 | 38 | if (StringUtils.isBlank(request.getAppName())) { 39 | return new SdsResponse(SdsCode.PARAM_ERROR.getCode(), "应用名称不能为空"); 40 | } 41 | 42 | List list = pointDictService.queryAllPointDictList(request.getAppGroupName(), request.getAppName()); 43 | 44 | return new SdsResponse(Lists.transform(list, (pointDictDO) -> pointDictDO.getPoint())); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/bean/DashboardPoint.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.bean; 2 | 3 | /** 4 | * @Description: 仪表盘数据上的一个点 5 | * @Author: manzhizhen 6 | * @Date: Create in 2019-09-13 17:15 7 | */ 8 | public class DashboardPoint { 9 | 10 | private Long timestamp; 11 | 12 | private Double value; 13 | 14 | public DashboardPoint() { 15 | } 16 | 17 | public DashboardPoint(Long timestamp, Double value) { 18 | this.timestamp = timestamp; 19 | this.value = value; 20 | } 21 | 22 | public Long getTimestamp() { 23 | return timestamp; 24 | } 25 | 26 | public void setTimestamp(Long timestamp) { 27 | this.timestamp = timestamp; 28 | } 29 | 30 | public Double getValue() { 31 | return value; 32 | } 33 | 34 | public void setValue(Double value) { 35 | this.value = value; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | final StringBuilder sb = new StringBuilder("DashboardPoint{"); 41 | sb.append("timestamp=").append(timestamp); 42 | sb.append(", value=").append(value); 43 | sb.append('}'); 44 | return sb.toString(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/bean/PageInfo.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.bean; 2 | 3 | /** 4 | * Created by manzhizhen on 18/9/29. 5 | */ 6 | public class PageInfo { 7 | 8 | protected Integer page; 9 | 10 | protected Integer pageSize; 11 | 12 | public Integer getPage() { 13 | return page; 14 | } 15 | 16 | public void setPage(Integer page) { 17 | this.page = page; 18 | } 19 | 20 | public Integer getPageSize() { 21 | return pageSize; 22 | } 23 | 24 | public void setPageSize(Integer pageSize) { 25 | this.pageSize = pageSize; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | final StringBuilder sb = new StringBuilder("PageInfo{"); 31 | sb.append("page=").append(page); 32 | sb.append(", pageSize=").append(pageSize); 33 | sb.append('}'); 34 | return sb.toString(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/bean/PointDictVO.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by tianyulei on 2019/8/11 7 | **/ 8 | public class PointDictVO implements Serializable { 9 | private static final long serialVersionUID = 1735890133713939995L; 10 | 11 | /** 12 | * 应用组名称 13 | */ 14 | private String appGroupName; 15 | 16 | /** 17 | * 应用名称 18 | */ 19 | private String appName; 20 | 21 | /** 22 | * 降级点,即对应的名称 23 | */ 24 | private String point; 25 | 26 | public String getAppGroupName() { 27 | return appGroupName; 28 | } 29 | 30 | public void setAppGroupName(String appGroupName) { 31 | this.appGroupName = appGroupName; 32 | } 33 | 34 | public String getAppName() { 35 | return appName; 36 | } 37 | 38 | public void setAppName(String appName) { 39 | this.appName = appName; 40 | } 41 | 42 | public String getPoint() { 43 | return point; 44 | } 45 | 46 | public void setPoint(String point) { 47 | this.point = point; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | final StringBuilder sb = new StringBuilder("PointDictVO{"); 53 | sb.append("appGroupName='").append(appGroupName).append('\''); 54 | sb.append(", appName='").append(appName).append('\''); 55 | sb.append(", point='").append(point).append('\''); 56 | sb.append('}'); 57 | return sb.toString(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/request/AbstractRequest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.request; 2 | 3 | import com.didiglobal.sds.admin.controller.bean.PageInfo; 4 | 5 | /** 6 | * @Author: manzhizhen 7 | * @Date: Create in 2020-03-22 20:48 8 | */ 9 | public abstract class AbstractRequest extends PageInfo { 10 | 11 | protected String operatorName = ""; 12 | 13 | protected String operatorEmail = ""; 14 | 15 | protected String creatorName = ""; 16 | 17 | protected String creatorEmail = ""; 18 | 19 | public String getOperatorName() { 20 | return operatorName; 21 | } 22 | 23 | public void setOperatorName(String operatorName) { 24 | this.operatorName = operatorName; 25 | } 26 | 27 | public String getOperatorEmail() { 28 | return operatorEmail; 29 | } 30 | 31 | public void setOperatorEmail(String operatorEmail) { 32 | this.operatorEmail = operatorEmail; 33 | } 34 | 35 | public String getCreatorName() { 36 | return creatorName; 37 | } 38 | 39 | public void setCreatorName(String creatorName) { 40 | this.creatorName = creatorName; 41 | } 42 | 43 | public String getCreatorEmail() { 44 | return creatorEmail; 45 | } 46 | 47 | public void setCreatorEmail(String creatorEmail) { 48 | this.creatorEmail = creatorEmail; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/request/AppGroupRequest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.request; 2 | 3 | /** 4 | * Created by manzhizhen on 18/9/29. 5 | */ 6 | public class AppGroupRequest extends AbstractRequest { 7 | 8 | private String appGroupName; 9 | 10 | private String newAppGroupName; 11 | 12 | public String getAppGroupName() { 13 | return appGroupName; 14 | } 15 | 16 | public void setAppGroupName(String appGroupName) { 17 | this.appGroupName = appGroupName; 18 | } 19 | 20 | public String getNewAppGroupName() { 21 | return newAppGroupName; 22 | } 23 | 24 | public void setNewAppGroupName(String newAppGroupName) { 25 | this.newAppGroupName = newAppGroupName; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | final StringBuilder sb = new StringBuilder("AppGroupRequest{"); 31 | sb.append("appGroupName='").append(appGroupName).append('\''); 32 | sb.append(", newAppGroupName='").append(newAppGroupName).append('\''); 33 | sb.append(", operatorName='").append(operatorName).append('\''); 34 | sb.append(", operatorEmail='").append(operatorEmail).append('\''); 35 | sb.append(", creatorName='").append(creatorName).append('\''); 36 | sb.append(", creatorEmail='").append(creatorEmail).append('\''); 37 | sb.append(", page=").append(page); 38 | sb.append(", pageSize=").append(pageSize); 39 | sb.append('}'); 40 | return sb.toString(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/request/AppInfoRequest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.request; 2 | 3 | /** 4 | * app信息请求 5 | * 6 | * @author manzhizhen 7 | */ 8 | public class AppInfoRequest extends AbstractRequest { 9 | 10 | private String appGroupName; 11 | 12 | private String appName; 13 | 14 | private String newAppName; 15 | 16 | private String sdsSchemeName; 17 | 18 | private String newSdsSchemeName; 19 | 20 | public String getAppGroupName() { 21 | return appGroupName; 22 | } 23 | 24 | public void setAppGroupName(String appGroupName) { 25 | this.appGroupName = appGroupName; 26 | } 27 | 28 | public String getAppName() { 29 | return appName; 30 | } 31 | 32 | public void setAppName(String appName) { 33 | this.appName = appName; 34 | } 35 | 36 | public String getNewAppName() { 37 | return newAppName; 38 | } 39 | 40 | public void setNewAppName(String newAppName) { 41 | this.newAppName = newAppName; 42 | } 43 | 44 | public String getSdsSchemeName() { 45 | return sdsSchemeName; 46 | } 47 | 48 | public void setSdsSchemeName(String sdsSchemeName) { 49 | this.sdsSchemeName = sdsSchemeName; 50 | } 51 | 52 | public String getNewSdsSchemeName() { 53 | return newSdsSchemeName; 54 | } 55 | 56 | public void setNewSdsSchemeName(String newSdsSchemeName) { 57 | this.newSdsSchemeName = newSdsSchemeName; 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | final StringBuilder sb = new StringBuilder("AppInfoRequest{"); 63 | sb.append("appGroupName='").append(appGroupName).append('\''); 64 | sb.append(", appName='").append(appName).append('\''); 65 | sb.append(", newAppName='").append(newAppName).append('\''); 66 | sb.append(", sdsSchemeName='").append(sdsSchemeName).append('\''); 67 | sb.append(", newSdsSchemeName='").append(newSdsSchemeName).append('\''); 68 | sb.append(", operatorName='").append(operatorName).append('\''); 69 | sb.append(", operatorEmail='").append(operatorEmail).append('\''); 70 | sb.append(", creatorName='").append(creatorName).append('\''); 71 | sb.append(", creatorEmail='").append(creatorEmail).append('\''); 72 | sb.append(", page=").append(page); 73 | sb.append(", pageSize=").append(pageSize); 74 | sb.append('}'); 75 | return sb.toString(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/request/DashboardPointRequest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.request; 2 | 3 | import com.didiglobal.sds.admin.controller.bean.PageInfo; 4 | 5 | /** 6 | * @Description: 监控大盘页面的查询请求 7 | * @Author: manzhizhen 8 | * @Date: Create in 2019-10-02 16:39 9 | */ 10 | public class DashboardPointRequest extends PageInfo { 11 | 12 | private String appGroupName; 13 | 14 | private String appName; 15 | 16 | private String point; 17 | 18 | public String getAppGroupName() { 19 | return appGroupName; 20 | } 21 | 22 | public void setAppGroupName(String appGroupName) { 23 | this.appGroupName = appGroupName; 24 | } 25 | 26 | public String getAppName() { 27 | return appName; 28 | } 29 | 30 | public void setAppName(String appName) { 31 | this.appName = appName; 32 | } 33 | 34 | public String getPoint() { 35 | return point; 36 | } 37 | 38 | public void setPoint(String point) { 39 | this.point = point; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | final StringBuilder sb = new StringBuilder("DashboardPointRequest{"); 45 | sb.append("appGroupName='").append(appGroupName).append('\''); 46 | sb.append(", appName='").append(appName).append('\''); 47 | sb.append(", point='").append(point).append('\''); 48 | sb.append('}'); 49 | return sb.toString(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/request/DashboardRequest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.request; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * @Description: 仪表盘降级点查询请求 7 | * @Author: manzhizhen 8 | * @Date: Create in 2019-09-13 12:22 9 | */ 10 | public class DashboardRequest { 11 | 12 | private String appGroupName; 13 | 14 | private String appName; 15 | 16 | private String point; 17 | 18 | private Date startTime; 19 | 20 | private Date endTime; 21 | 22 | public String getAppGroupName() { 23 | return appGroupName; 24 | } 25 | 26 | public void setAppGroupName(String appGroupName) { 27 | this.appGroupName = appGroupName; 28 | } 29 | 30 | public String getAppName() { 31 | return appName; 32 | } 33 | 34 | public void setAppName(String appName) { 35 | this.appName = appName; 36 | } 37 | 38 | public String getPoint() { 39 | return point; 40 | } 41 | 42 | public void setPoint(String point) { 43 | this.point = point; 44 | } 45 | 46 | public Date getStartTime() { 47 | return startTime; 48 | } 49 | 50 | public void setStartTime(Date startTime) { 51 | this.startTime = startTime; 52 | } 53 | 54 | public Date getEndTime() { 55 | return endTime; 56 | } 57 | 58 | public void setEndTime(Date endTime) { 59 | this.endTime = endTime; 60 | } 61 | 62 | @Override 63 | public String toString() { 64 | final StringBuilder sb = new StringBuilder("DashboardRequest{"); 65 | sb.append("appGroupName='").append(appGroupName).append('\''); 66 | sb.append(", appName='").append(appName).append('\''); 67 | sb.append(", point='").append(point).append('\''); 68 | sb.append(", startTime=").append(startTime); 69 | sb.append(", endTime=").append(endTime); 70 | sb.append('}'); 71 | return sb.toString(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/request/HeartbeatQueryRequest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.request; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * 心跳查询请求 7 | * 8 | * @author manzhizhen 9 | */ 10 | public class HeartbeatQueryRequest { 11 | 12 | private String appGroupName; 13 | 14 | private String appName; 15 | 16 | private String point; 17 | 18 | private Date startTime; 19 | 20 | private Date endTime; 21 | 22 | public String getAppGroupName() { 23 | return appGroupName; 24 | } 25 | 26 | public void setAppGroupName(String appGroupName) { 27 | this.appGroupName = appGroupName; 28 | } 29 | 30 | public String getAppName() { 31 | return appName; 32 | } 33 | 34 | public void setAppName(String appName) { 35 | this.appName = appName; 36 | } 37 | 38 | public String getPoint() { 39 | return point; 40 | } 41 | 42 | public void setPoint(String point) { 43 | this.point = point; 44 | } 45 | 46 | public Date getStartTime() { 47 | return startTime; 48 | } 49 | 50 | public void setStartTime(Date startTime) { 51 | this.startTime = startTime; 52 | } 53 | 54 | public Date getEndTime() { 55 | return endTime; 56 | } 57 | 58 | public void setEndTime(Date endTime) { 59 | this.endTime = endTime; 60 | } 61 | 62 | @Override 63 | public String toString() { 64 | final StringBuilder sb = new StringBuilder("HeartbeatQueryRequest{"); 65 | sb.append("appGroupName='").append(appGroupName).append('\''); 66 | sb.append(", appName='").append(appName).append('\''); 67 | sb.append(", point='").append(point).append('\''); 68 | sb.append(", startTime=").append(startTime); 69 | sb.append(", endTime=").append(endTime); 70 | sb.append('}'); 71 | return sb.toString(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/request/PointDictRequest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.request; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by tianyulei on 2019/8/11 7 | **/ 8 | public class PointDictRequest implements Serializable { 9 | private static final long serialVersionUID = -6263204439209038271L; 10 | 11 | private String appGroupName; 12 | 13 | private String appName; 14 | 15 | public String getAppGroupName() { 16 | return appGroupName; 17 | } 18 | 19 | public void setAppGroupName(String appGroupName) { 20 | this.appGroupName = appGroupName; 21 | } 22 | 23 | public String getAppName() { 24 | return appName; 25 | } 26 | 27 | public void setAppName(String appName) { 28 | this.appName = appName; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | final StringBuilder sb = new StringBuilder("PointDictRequest{"); 34 | sb.append("appGroupName='").append(appGroupName).append('\''); 35 | sb.append(", appName='").append(appName).append('\''); 36 | sb.append('}'); 37 | return sb.toString(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/request/SdsSchemeRequest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.request; 2 | 3 | /** 4 | * Created by manzhizhen on 18/9/29. 5 | */ 6 | public class SdsSchemeRequest extends AbstractRequest { 7 | 8 | private String appGroupName; 9 | 10 | private String appName; 11 | 12 | private String sdsSchemeName; 13 | 14 | private String newSdsSchemeName; 15 | 16 | public String getAppGroupName() { 17 | return appGroupName; 18 | } 19 | 20 | public void setAppGroupName(String appGroupName) { 21 | this.appGroupName = appGroupName; 22 | } 23 | 24 | public String getAppName() { 25 | return appName; 26 | } 27 | 28 | public void setAppName(String appName) { 29 | this.appName = appName; 30 | } 31 | 32 | public String getSdsSchemeName() { 33 | return sdsSchemeName; 34 | } 35 | 36 | public void setSdsSchemeName(String sdsSchemeName) { 37 | this.sdsSchemeName = sdsSchemeName; 38 | } 39 | 40 | public String getNewSdsSchemeName() { 41 | return newSdsSchemeName; 42 | } 43 | 44 | public void setNewSdsSchemeName(String newSdsSchemeName) { 45 | this.newSdsSchemeName = newSdsSchemeName; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | final StringBuilder sb = new StringBuilder("SdsSchemeRequest{"); 51 | sb.append("appGroupName='").append(appGroupName).append('\''); 52 | sb.append(", appName='").append(appName).append('\''); 53 | sb.append(", sdsSchemeName='").append(sdsSchemeName).append('\''); 54 | sb.append(", newSdsSchemeName='").append(newSdsSchemeName).append('\''); 55 | sb.append(", operatorName='").append(operatorName).append('\''); 56 | sb.append(", operatorEmail='").append(operatorEmail).append('\''); 57 | sb.append(", creatorName='").append(creatorName).append('\''); 58 | sb.append(", creatorEmail='").append(creatorEmail).append('\''); 59 | sb.append(", page=").append(page); 60 | sb.append(", pageSize=").append(pageSize); 61 | sb.append('}'); 62 | return sb.toString(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/controller/response/SdsResponse.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.controller.response; 2 | 3 | import com.didiglobal.sds.admin.constants.SdsCode; 4 | 5 | public class SdsResponse { 6 | 7 | private Integer code; 8 | 9 | private String msg; 10 | 11 | private T data; 12 | 13 | public SdsResponse() { 14 | } 15 | 16 | public SdsResponse(Integer code, String msg) { 17 | this.code = code; 18 | this.msg = msg; 19 | } 20 | 21 | public SdsResponse(T data) { 22 | this.code = SdsCode.SUCCESS.getCode(); 23 | this.data = data; 24 | } 25 | 26 | public Integer getCode() { 27 | return code; 28 | } 29 | 30 | public void setCode(Integer code) { 31 | this.code = code; 32 | } 33 | 34 | public String getMsg() { 35 | return msg; 36 | } 37 | 38 | public void setMsg(String msg) { 39 | this.msg = msg; 40 | } 41 | 42 | public T getData() { 43 | return data; 44 | } 45 | 46 | public void setData(T data) { 47 | this.data = data; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | final StringBuilder sb = new StringBuilder("SdsResponse{"); 53 | sb.append("code=").append(code); 54 | sb.append(", msg='").append(msg).append('\''); 55 | sb.append(", data=").append(data); 56 | sb.append('}'); 57 | return sb.toString(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/dao/UserPrivilegeDao.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.dao; 2 | 3 | import com.didiglobal.sds.admin.dao.bean.UserPrivilege; 4 | import org.apache.ibatis.annotations.Insert; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Result; 7 | import org.apache.ibatis.annotations.Results; 8 | import org.apache.ibatis.annotations.Select; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * 用户权限DAO 14 | * 15 | * @auther manzhizhen 16 | * @date 2019/1/18 17 | */ 18 | public interface UserPrivilegeDao { 19 | 20 | /** 21 | * 给某个用户新增权限 22 | * 23 | * @param userName 24 | * @param appGroupName 25 | * @param appName 26 | * @return 27 | */ 28 | @Insert("") 34 | int addUserPrivilege(@Param("userName") String userName, 35 | @Param("userPrivilegeList") List userPrivilegeList); 36 | 37 | /** 38 | * 查询某个用户权限 39 | * 40 | * @param userName 41 | * @param appGroupName 42 | * @param appName 43 | * @return 44 | */ 45 | @Select("select * from user_privilege where user_name = #{userName} limit #{start}, #{size}") 46 | @Results({ 47 | @Result(property = "id", column = "id"), 48 | @Result(property = "userName", column = "user_name"), 49 | @Result(property = "appGroupName", column = "app_group_name"), 50 | @Result(property = "appName", column = "app_name"), 51 | @Result(property = "sdsSchemeName", column = "sds_scheme_name"), 52 | @Result(property = "modifiedTime", column = "modify_time"), 53 | @Result(property = "createTime", column = "create_time") 54 | }) 55 | List queryUserPrivilegeByPage(@Param("userName") String userName, @Param("start") Integer start, 56 | @Param("size") Integer size); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/remote/SdsRestTemplate.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.remote; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.http.client.SimpleClientHttpRequestFactory; 6 | import org.springframework.web.client.RestTemplate; 7 | 8 | /** 9 | * @Description: 10 | * @Author: manzhizhen 11 | * @Date: Create in 2019-09-15 08:48 12 | */ 13 | @Configuration 14 | public class SdsRestTemplate { 15 | 16 | @Bean 17 | public RestTemplate restTemplate() { 18 | SimpleClientHttpRequestFactory httpRequestFactory = new SimpleClientHttpRequestFactory(); 19 | httpRequestFactory.setConnectTimeout(1000); 20 | httpRequestFactory.setReadTimeout(1000); 21 | 22 | return new RestTemplate(httpRequestFactory); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/service/DashboardService.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.service; 2 | 3 | import com.didiglobal.sds.admin.service.bean.DashboardMainBO; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * @Description: 降级仪表盘服务接口 9 | * @Author: manzhizhen 10 | * @Date: Create in 2019-10-01 11:16 11 | */ 12 | public interface DashboardService { 13 | 14 | /** 15 | * 通过时间范围查询某个降级点的展示信息 16 | * 17 | * @param appGroupName 18 | * @param appName 19 | * @param point 20 | * @param tartTime 21 | * @param endTime 22 | * @return 23 | */ 24 | DashboardMainBO queryDashboardMainShowInfo(String appGroupName, String appName, String point, Date tartTime, 25 | Date endTime); 26 | } 27 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/service/HeartbeatService.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.service; 2 | 3 | import com.didiglobal.sds.client.bean.HeartBeatResponse; 4 | import com.didiglobal.sds.client.bean.HeartbeatRequest; 5 | import com.didiglobal.sds.admin.service.bean.HeartbeatShowBO; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * Created by manzhizhen on 18/2/12. 11 | */ 12 | public interface HeartbeatService { 13 | 14 | /** 15 | * 保存心跳数据 16 | * 17 | * @param heartbeatRequest 18 | * @return 19 | */ 20 | HeartBeatResponse saveHeartbeatInfo(HeartbeatRequest heartbeatRequest); 21 | 22 | /** 23 | * 检查并拉取最新的降级点策略配置 24 | * 25 | * @param heartbeatRequest 26 | * @return 27 | */ 28 | HeartBeatResponse checkAndGetNewestPointStrategy(HeartbeatRequest heartbeatRequest); 29 | 30 | /** 31 | * 按条件查询心跳数据 32 | * 33 | * @param appGroupName 34 | * @param appName 35 | * @param point 36 | * @param startTime 37 | * @param endTime 38 | * @return 39 | */ 40 | HeartbeatShowBO queryHeartbeatList(String appGroupName, String appName, String point, Date startTime, Date endTime); 41 | } 42 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/service/PointDictService.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.service; 2 | 3 | import com.didiglobal.sds.client.bean.SdsCycleInfo; 4 | import com.didiglobal.sds.admin.dao.bean.PointDictDO; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * 降级点字典表数据新增 11 | * Created by tianyulei on 2019/7/10 12 | **/ 13 | public interface PointDictService { 14 | 15 | /** 16 | * 如果降级点不存在则新增 17 | * 18 | * @param appGroupName 19 | * @param appName 20 | * @param point 21 | */ 22 | Boolean addIfNotExist(String appGroupName, String appName, String point); 23 | 24 | /** 25 | * 批量新增降级点 26 | * 新增前会判断降级点是否存在 27 | * 28 | * @param list 29 | * @return 30 | */ 31 | void addPointList(List list); 32 | 33 | /** 34 | * 查询该应用所有降级字典列表 35 | * 36 | * @param appGroupName 37 | * @param appName 38 | * @return 39 | */ 40 | List queryAllPointDictList(String appGroupName, String appName); 41 | 42 | /** 43 | * 分页查询该应用降级字典列表 44 | * 45 | * @param appGroupName 46 | * @param appName 47 | * @param point 该字段模糊查询 48 | * @param page 49 | * @param pageSize 50 | * @return 51 | */ 52 | List queryPointDictListByPage(String appGroupName, String appName, String point, Integer page, 53 | Integer pageSize); 54 | 55 | /** 56 | * 检查应用中的降级点是否与库里一直,若库里的降级点更多,且满足一定周期,则认定其为无效降级点,需进行删除 57 | * 58 | * @param map 59 | * @param appGroupName 60 | * @param appName 61 | */ 62 | void checkAndDeleteDeadPoint(Map map, String appGroupName, String appName); 63 | } 64 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/service/bean/DashboardMainBO.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.service.bean; 2 | 3 | import com.didiglobal.sds.admin.controller.bean.DashboardPoint; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @Description: 仪表盘主要显示的信息 9 | * @Author: manzhizhen 10 | * @Date: Create in 2019-10-01 11:18 11 | */ 12 | public class DashboardMainBO { 13 | 14 | private List visitList; 15 | 16 | private List concurrentList; 17 | 18 | private List exceptionList; 19 | 20 | private List timeoutList; 21 | 22 | private List downgradeList; 23 | 24 | public List getVisitList() { 25 | return visitList; 26 | } 27 | 28 | public void setVisitList(List visitList) { 29 | this.visitList = visitList; 30 | } 31 | 32 | public List getConcurrentList() { 33 | return concurrentList; 34 | } 35 | 36 | public void setConcurrentList(List concurrentList) { 37 | this.concurrentList = concurrentList; 38 | } 39 | 40 | public List getExceptionList() { 41 | return exceptionList; 42 | } 43 | 44 | public void setExceptionList(List exceptionList) { 45 | this.exceptionList = exceptionList; 46 | } 47 | 48 | public List getTimeoutList() { 49 | return timeoutList; 50 | } 51 | 52 | public void setTimeoutList(List timeoutList) { 53 | this.timeoutList = timeoutList; 54 | } 55 | 56 | public List getDowngradeList() { 57 | return downgradeList; 58 | } 59 | 60 | public void setDowngradeList(List downgradeList) { 61 | this.downgradeList = downgradeList; 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | final StringBuilder sb = new StringBuilder("DashboardMainBO{"); 67 | sb.append("visitList=").append(visitList); 68 | sb.append(", concurrentList=").append(concurrentList); 69 | sb.append(", exceptionList=").append(exceptionList); 70 | sb.append(", timeoutList=").append(timeoutList); 71 | sb.append(", downgradeList=").append(downgradeList); 72 | sb.append('}'); 73 | return sb.toString(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/service/bean/HeartbeatShowBO.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.service.bean; 2 | 3 | import java.util.List; 4 | 5 | public class HeartbeatShowBO { 6 | 7 | /** 8 | * 应用组名字 9 | */ 10 | private String appGroupName; 11 | 12 | /** 13 | * 应用名称(冗余数据) 14 | */ 15 | private String appName; 16 | 17 | /** 18 | * 降级点 19 | */ 20 | private String point; 21 | 22 | private List heartbeatList; 23 | 24 | public HeartbeatShowBO() { 25 | } 26 | 27 | public HeartbeatShowBO(String appGroupName, String appName, String point, List heartbeatList) { 28 | this.appGroupName = appGroupName; 29 | this.appName = appName; 30 | this.point = point; 31 | this.heartbeatList = heartbeatList; 32 | } 33 | 34 | public String getAppGroupName() { 35 | return appGroupName; 36 | } 37 | 38 | public void setAppGroupName(String appGroupName) { 39 | this.appGroupName = appGroupName; 40 | } 41 | 42 | public String getAppName() { 43 | return appName; 44 | } 45 | 46 | public void setAppName(String appName) { 47 | this.appName = appName; 48 | } 49 | 50 | public String getPoint() { 51 | return point; 52 | } 53 | 54 | public void setPoint(String point) { 55 | this.point = point; 56 | } 57 | 58 | public List getHeartbeatList() { 59 | return heartbeatList; 60 | } 61 | 62 | public void setHeartbeatList(List heartbeatList) { 63 | this.heartbeatList = heartbeatList; 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | final StringBuilder sb = new StringBuilder("HeartbeatShowBO{"); 69 | sb.append("appGroupName='").append(appGroupName).append('\''); 70 | sb.append(", appName='").append(appName).append('\''); 71 | sb.append(", point='").append(point).append('\''); 72 | sb.append(", heartbeatList=").append(heartbeatList); 73 | sb.append('}'); 74 | return sb.toString(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/util/HttpResponse.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.util; 2 | 3 | /** 4 | * Created by manzhizhen on 17/6/28. 5 | */ 6 | public class HttpResponse { 7 | 8 | private String result; 9 | 10 | private int code; 11 | 12 | private Exception exception; 13 | 14 | public boolean isSuccessful() { 15 | return code >= 200 && code < 300; 16 | } 17 | 18 | public String getResult() { 19 | return result; 20 | } 21 | 22 | public void setResult(String result) { 23 | this.result = result; 24 | } 25 | 26 | public int getCode() { 27 | return code; 28 | } 29 | 30 | public void setCode(int code) { 31 | this.code = code; 32 | } 33 | 34 | public Exception getException() { 35 | return exception; 36 | } 37 | 38 | public void setException(Exception exception) { 39 | this.exception = exception; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | final StringBuilder sb = new StringBuilder("HttpResponse{"); 45 | sb.append("result='").append(result).append('\''); 46 | sb.append(", code=").append(code); 47 | sb.append(", exception=").append(exception); 48 | sb.append('}'); 49 | return sb.toString(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /sds-admin/src/main/java/com/didiglobal/sds/admin/util/StringCheck.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.util; 2 | 3 | import com.didiglobal.sds.client.util.StringUtils; 4 | 5 | import java.util.regex.Pattern; 6 | 7 | /** 8 | * 字符工具类 9 | * 10 | * @author manzhizhen 11 | * @date 2019-01-28 12 | */ 13 | public final class StringCheck { 14 | 15 | /** 16 | * 中文字符的正则 17 | */ 18 | private static Pattern pattern = Pattern.compile("[\\u4E00-\\u9FBF]+"); 19 | 20 | /** 21 | * 检查名字,限制字母、数字和"-" 22 | * 23 | * @param name 24 | * @return 25 | */ 26 | public static boolean checkStringName(String name) { 27 | if (StringUtils.isBlank(name)) { 28 | return true; 29 | } 30 | 31 | for (char c : name.toCharArray()) { 32 | if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || 33 | c == '#') { 34 | continue; 35 | } 36 | 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | 43 | /** 44 | * 检查名字,限制汉字、字母、数字和"-" 45 | * 46 | * @param name 47 | * @return 48 | */ 49 | public static boolean checkChineseStringName(String name) { 50 | if (StringUtils.isBlank(name)) { 51 | return true; 52 | } 53 | 54 | for (char c : name.toCharArray()) { 55 | if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || 56 | isChinese(c)) { 57 | continue; 58 | } 59 | 60 | return false; 61 | } 62 | 63 | return true; 64 | } 65 | 66 | 67 | /** 68 | * 是否是汉字 69 | * 70 | * @param value 71 | * @return 72 | */ 73 | public static boolean isChinese(char value) { 74 | return pattern.matcher(String.valueOf(value)).find(); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /sds-admin/src/main/resources/config/application-dev.properties: -------------------------------------------------------------------------------- 1 | # sds保持海量心跳数据所选择的数据库类型(注意:当前只支持 mysql、h2、influxdb、es 四种数据库) 2 | sds.heartbeat.database.type=h2 3 | 4 | logging.level.com.didiglobal.sds.admin.dao=debug 5 | 6 | # 开发环境一般用h2 7 | spring.datasource.driverClassName=org.h2.Driver 8 | spring.datasource.username=sa 9 | spring.datasource.password=sa 10 | spring.datasource.url=jdbc:h2:~/test 11 | spring.datasource.schema=classpath:db/h2.sql 12 | 13 | # 当然你也可以用mysql 14 | #aspectj.datasource.driverClassName=com.mysql.jdbc.Driver 15 | #aspectj.datasource.username= 16 | #aspectj.datasource.password= 17 | #aspectj.datasource.url=jdbc:mysql:// 18 | #aspectj.datasource.schema=classpath:db/mysql.sql 19 | 20 | # 如果sds.heartbeat.database.type为influxdb,那么需要配置influxdb相关信息 21 | sds.influxdb.username=sa 22 | sds.influxdb.password=sa 23 | sds.influxdb.url=http://localhost:8086 24 | sds.influxdb.database=sds 25 | 26 | # 日志配置 27 | #logging.config=classpath:config/logback.xml 28 | #sds.log.dir=/home/xiaoju/logs/sds 29 | #sds.log.level=info 30 | 31 | # web服务暴露的端口 32 | server.port=8887 -------------------------------------------------------------------------------- /sds-admin/src/main/resources/config/application-docker.properties: -------------------------------------------------------------------------------- 1 | # sds保持海量心跳数据所选择的数据库类型(注意:当前只支持 mysql、h2、influxdb、es 四种数据库) 2 | sds.heartbeat.database.type=${SDS_HEARTBEAT_DATABASE_TYPE} 3 | 4 | logging.level.com.didiglobal.sds.web.dao=debug 5 | 6 | # 开发环境一般用h2 7 | spring.datasource.driverClassName=${SPRING_DATASOURCE_DRIVER_CLASS_NAME} 8 | spring.datasource.username=${SPRING_DATASOURCE_USERNAME} 9 | spring.datasource.password=${SPRING_DATASOURCE_PASSWORD} 10 | spring.datasource.url=${SPRING_DATASOURCE_URL} 11 | spring.datasource.schema=${SPRING_DATASOURCE_SCHEMA} 12 | 13 | # 当然你也可以用mysql 14 | #spring.datasource.driverClassName=com.mysql.jdbc.Driver 15 | #spring.datasource.username= 16 | #spring.datasource.password= 17 | #spring.datasource.url=jdbc:mysql:// 18 | #spring.datasource.schema=classpath:db/mysql.sql 19 | 20 | # 如果sds.heartbeat.database.type为influxdb,那么需要配置influxdb相关信息 21 | sds.influxdb.username=${SDS_INFLUXDB_USERNAME} 22 | sds.influxdb.password=${SDS_INFLUXDB_PASSWORD} 23 | sds.influxdb.url=${SDS_INFLUXDB_URL} 24 | sds.influxdb.database=${SDS_INFLUXDB_DATABASE} 25 | 26 | # 日志配置 27 | #logging.config=classpath:config/logback.xml 28 | #sds.log.dir=/home/xiaoju/logs/sds 29 | #sds.log.level=info 30 | 31 | # web服务暴露的端口 32 | server.port=8887 -------------------------------------------------------------------------------- /sds-admin/src/main/resources/config/application-online.properties: -------------------------------------------------------------------------------- 1 | # sds保持海量心跳数据所选择的数据库类型(注意:当前只支持 mysql、h2、influxdb、es 四种数据库) 2 | sds.heartbeat.database.type=influxdb 3 | 4 | # 线上一般用mysql 5 | spring.datasource.driverClassName=com.mysql.jdbc.Driver 6 | spring.datasource.username= 7 | spring.datasource.password= 8 | spring.datasource.url=jdbc:mysql:// 9 | 10 | # 日志配置 11 | logging.config=classpath:config/logback.xml 12 | sds.log.dir= 13 | sds.log.level=info 14 | 15 | # 如果sds.heartbeat.database.type为influxdb,那么需要配置influxdb相关信息 16 | sds.influxdb.username= 17 | sds.influxdb.password= 18 | sds.influxdb.url= 19 | sds.influxdb.database= 20 | 21 | # web服务暴露的端口 22 | server.port=8887 23 | 24 | 25 | -------------------------------------------------------------------------------- /sds-admin/src/main/resources/config/application.properties: -------------------------------------------------------------------------------- 1 | # 当前是什么环境(即用什么profile) 2 | spring.profiles.active=dev -------------------------------------------------------------------------------- /sds-admin/src/main/resources/config/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | [%-5level] %date{yyyy-MM-dd HH:mm:ss.SSS} %m%n 13 | 14 | 15 | 16 | ${ROOT}/heartbeat.%d.log 17 | 18 | 19 | 20 | 21 | 22 | [%-5level] %date{yyyy-MM-dd HH:mm:ss.SSS} %m%n 23 | 24 | 25 | 26 | ${ROOT}/pullstrategy.%d.log 27 | 28 | 29 | 30 | 31 | 32 | [%-5level] %date{yyyy-MM-dd HH:mm:ss.SSS} %m%n 33 | 34 | 35 | 36 | ${ROOT}/Sds.%d.log 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/SdsAdminApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.test.context.TestPropertySource; 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 | 8 | @RunWith(SpringJUnit4ClassRunner.class) 9 | @TestPropertySource("classpath:config/application.properties") 10 | public class SdsAdminApplicationTest { 11 | 12 | @Test 13 | public void mainTest () { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/controller/AppGroupControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.controller; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.didiglobal.sds.admin.controller.AppGroupController; 5 | import com.didiglobal.sds.admin.controller.request.AppGroupRequest; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | import org.springframework.test.web.servlet.MockMvc; 12 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 13 | 14 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 15 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 16 | 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest 19 | public class AppGroupControllerTest { 20 | 21 | @Autowired 22 | private AppGroupController appGroupController; 23 | 24 | @Test 25 | public void queryAppGroupByPageTest() { 26 | 27 | MockMvc mockMvc = MockMvcBuilders.standaloneSetup(appGroupController).build(); 28 | try { 29 | AppGroupRequest request = new AppGroupRequest(); 30 | request.setAppGroupName("BikeBusinessDepartment"); 31 | request.setOperatorName("路飞"); 32 | request.setOperatorEmail("manzhizhen@didiglobal.com"); 33 | request.setCreatorName("路飞"); 34 | request.setCreatorEmail("manzhizhen@didiglobal.com"); 35 | request.setPage(1); 36 | request.setPageSize(10); 37 | 38 | mockMvc.perform(post("/sds/appgroup/listpage").contentType("application/json").content(JSON.toJSONString(request)) 39 | ).andDo(print()); 40 | 41 | } catch (Exception e) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/controller/AppInfoControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.controller; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.didiglobal.sds.admin.controller.AppInfoController; 5 | import com.didiglobal.sds.admin.controller.request.AppInfoRequest; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | import org.springframework.test.web.servlet.MockMvc; 12 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 13 | 14 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 15 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 16 | 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest 19 | public class AppInfoControllerTest { 20 | 21 | @Autowired 22 | private AppInfoController appInfoController; 23 | 24 | @Test 25 | public void queryAppInfoByPageTest() { 26 | 27 | AppInfoRequest request = new AppInfoRequest(); 28 | request.setAppGroupName("BikeBusinessDepartment"); 29 | request.setAppName("order"); 30 | request.setSdsSchemeName("默认降级预案"); 31 | request.setOperatorName("路飞"); 32 | request.setOperatorEmail("manzhizhen@didiglobal.com"); 33 | request.setCreatorName("路飞"); 34 | request.setCreatorEmail("manzhizhen@didiglobal.com"); 35 | request.setPage(1); 36 | request.setPageSize(10); 37 | 38 | 39 | MockMvc mockMvc = MockMvcBuilders.standaloneSetup(appInfoController).build(); 40 | try { 41 | mockMvc.perform( 42 | post("/sds/appinfo/listpage").contentType("application/json").content(JSON.toJSONString(request)) 43 | ).andDo(print()); 44 | 45 | } catch (Exception e) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/controller/PointDictControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.controller; 2 | 3 | import com.didiglobal.sds.admin.controller.PointDictController; 4 | import com.didiglobal.sds.admin.controller.request.PointDictRequest; 5 | import com.didiglobal.sds.admin.controller.response.SdsResponse; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * Created by tianyulei on 2019/8/11 16 | **/ 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest 19 | public class PointDictControllerTest { 20 | 21 | @Autowired 22 | private PointDictController pointDictController; 23 | 24 | @Test 25 | public void testQueryList() { 26 | PointDictRequest pointDictRequest = new PointDictRequest(); 27 | pointDictRequest.setAppGroupName("htw"); 28 | pointDictRequest.setAppName("htw-user"); 29 | SdsResponse> list = pointDictController.queryPointDictList(pointDictRequest); 30 | System.out.println(list); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/controller/SdsSchemeControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.controller; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.didiglobal.sds.admin.controller.SdsSchemeController; 5 | import com.didiglobal.sds.admin.controller.request.SdsSchemeRequest; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.http.MediaType; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | import org.springframework.test.web.servlet.MockMvc; 13 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 14 | 15 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 16 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 17 | 18 | @RunWith(SpringRunner.class) 19 | @SpringBootTest 20 | public class SdsSchemeControllerTest { 21 | 22 | @Autowired 23 | private SdsSchemeController sdsSchemeController; 24 | 25 | @Test 26 | public void querySdsSchemeByPageTest() { 27 | 28 | SdsSchemeRequest request = new SdsSchemeRequest(); 29 | request.setAppGroupName("BikeBusinessDepartment"); 30 | request.setAppName("order"); 31 | request.setSdsSchemeName("默认降级策略"); 32 | request.setOperatorName("路飞"); 33 | request.setOperatorEmail("manzhizhen@didiglobal.com"); 34 | request.setCreatorName("路飞"); 35 | request.setCreatorEmail("manzhizhen@didiglobal.com"); 36 | request.setPage(1); 37 | request.setPageSize(10); 38 | 39 | 40 | MockMvc mockMvc = MockMvcBuilders.standaloneSetup(sdsSchemeController).build(); 41 | try { 42 | mockMvc.perform(post("/sds/sdsscheme/listpage").characterEncoding("UTF-8").contentType( 43 | MediaType.APPLICATION_JSON_UTF8) 44 | .content(JSON.toJSONString(request)) 45 | ).andDo(print()); 46 | 47 | } catch (Exception e) { 48 | e.printStackTrace(); 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/controller/StrategyPointControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.controller; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.didiglobal.sds.admin.controller.PointStrategyController; 5 | import com.didiglobal.sds.admin.controller.request.PointStrategyRequest; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.http.MediaType; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | import org.springframework.test.web.servlet.MockMvc; 13 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 14 | 15 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 16 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 17 | 18 | /** 19 | * Created by tianyulei on 2019/6/16 20 | **/ 21 | @RunWith(SpringRunner.class) 22 | @SpringBootTest 23 | public class StrategyPointControllerTest { 24 | 25 | @Autowired 26 | private PointStrategyController pointStrategyController; 27 | 28 | @Test 29 | public void queryAppCurSdsSchemeTipsTest() throws Exception { 30 | 31 | PointStrategyRequest request = new PointStrategyRequest(); 32 | request.setAppGroupName("应用组A"); 33 | request.setAppName("应用a"); 34 | request.setPage(1); 35 | request.setPageSize(10); 36 | 37 | MockMvc mockMvc = MockMvcBuilders.standaloneSetup(pointStrategyController).build(); 38 | mockMvc.perform( 39 | post("/sds/pointstrategy/add").characterEncoding("UTF-8").contentType(MediaType.APPLICATION_JSON_UTF8) 40 | .content(JSON.toJSONString(request)) 41 | ).andDo(print()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/dao/AppGroupDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.dao; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.didiglobal.sds.admin.dao.AppGroupDao; 5 | import com.didiglobal.sds.admin.dao.bean.AppGroupDO; 6 | import org.junit.Assert; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | /** 14 | * Created by manzhizhen on 18/2/12. 15 | */ 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest 18 | public class AppGroupDaoTest { 19 | 20 | @Autowired 21 | private AppGroupDao appGroupDao; 22 | 23 | @Test 24 | public void addAppGroupTest() { 25 | AppGroupDO appGroupDO = new AppGroupDO(); 26 | appGroupDO.setCreatorName("路飞"); 27 | appGroupDO.setOperatorName("路飞"); 28 | appGroupDO.setCreatorEmail("manzhizhen@didichuxing.com"); 29 | appGroupDO.setOperatorEmail("manzhizhen@didichuxing.com"); 30 | appGroupDO.setAppGroupName("黑马4"); 31 | Assert.assertEquals(1, appGroupDao.addAppGroup(appGroupDO)); 32 | 33 | appGroupDO.setAppGroupName("黑马5"); 34 | Assert.assertEquals(1, appGroupDao.addAppGroup(appGroupDO)); 35 | 36 | appGroupDO.setAppGroupName("黑马6"); 37 | Assert.assertEquals(1, appGroupDao.addAppGroup(appGroupDO)); 38 | } 39 | 40 | @Test 41 | public void queryAllAppGroupTest() { 42 | System.out.println(JSON.toJSONString(appGroupDao.queryAllAppGroup())); 43 | } 44 | 45 | @Test 46 | public void queryByGroupNameTest() { 47 | System.out.println(appGroupDao.queryByGroupName("黑马1")); 48 | } 49 | 50 | @Test 51 | public void queryAppGroupByPageTest() { 52 | System.out.println(appGroupDao.queryAppGroupByPage(" ", 1, 10)); 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/dao/AppInfoDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.dao; 2 | 3 | import com.didiglobal.sds.admin.dao.AppInfoDao; 4 | import com.didiglobal.sds.admin.dao.bean.AppInfoDO; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | /** 13 | * Created by manzhizhen on 18/2/12. 14 | */ 15 | @RunWith(SpringRunner.class) 16 | @SpringBootTest 17 | public class AppInfoDaoTest { 18 | 19 | @Autowired 20 | private AppInfoDao appInfoDao; 21 | 22 | @Test 23 | public void addAppInfoTest() { 24 | AppInfoDO appInfoDO = new AppInfoDO(); 25 | appInfoDO.setAppGroupName("黑马1"); 26 | appInfoDO.setAppName("bh-order"); 27 | appInfoDO.setCreatorEmail("manzhizhen@163.com"); 28 | appInfoDO.setCreatorName("manzhizhen"); 29 | appInfoDO.setOperatorEmail("manzhizhen@163.com"); 30 | appInfoDO.setOperatorName("manzhizhen"); 31 | Assert.assertEquals(1, appInfoDao.addAppInfo(appInfoDO)); 32 | 33 | appInfoDO.setAppGroupName("黑马1"); 34 | appInfoDO.setAppName("bh-order1"); 35 | Assert.assertEquals(1, appInfoDao.addAppInfo(appInfoDO)); 36 | 37 | appInfoDO.setAppGroupName("黑马1"); 38 | appInfoDO.setAppName("bh-order1"); 39 | try { 40 | appInfoDao.addAppInfo(appInfoDO); 41 | Assert.fail(); 42 | } catch (Exception e) { 43 | } 44 | 45 | appInfoDO.setAppGroupName("黑马2"); 46 | appInfoDO.setAppName("bh-order"); 47 | appInfoDO.setSdsSchemeName("FIRST_GREP"); 48 | Assert.assertEquals(1, appInfoDao.addAppInfo(appInfoDO)); 49 | } 50 | 51 | @Test 52 | public void queryAppInfoTest() { 53 | System.out.println(appInfoDao.queryAppInfo("BikeBusinessDepartment", "bh-order")); 54 | } 55 | 56 | @Test 57 | public void queryAppInfoByPageTest() { 58 | System.out.println(appInfoDao.queryAppInfoByPage(null, null, 1, 10)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/dao/HeartbeatDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.dao; 2 | import java.util.Date; 3 | import java.util.List; 4 | 5 | import com.didiglobal.sds.admin.dao.HeartbeatDao; 6 | import com.didiglobal.sds.admin.dao.bean.HeartbeatDO; 7 | import org.assertj.core.util.Lists; 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.boot.test.context.SpringBootTest; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | 15 | @RunWith(SpringRunner.class) 16 | @SpringBootTest 17 | public class HeartbeatDaoTest { 18 | 19 | @Autowired 20 | private HeartbeatDao heartbeatDao; 21 | 22 | @Test 23 | public void addHeartbeatTest() { 24 | List dataList = Lists.newArrayList(); 25 | HeartbeatDO heartbeatDO = new HeartbeatDO(); 26 | heartbeatDO.setAppGroupName("BikeBusinessDepartment"); 27 | heartbeatDO.setAppName("bh-order"); 28 | heartbeatDO.setPoint("testPoint"); 29 | heartbeatDO.setDowngradeNum(123L); 30 | heartbeatDO.setVisitNum(1000000L); 31 | heartbeatDO.setExceptionNum(234L); 32 | heartbeatDO.setTimeoutNum(1233L); 33 | heartbeatDO.setMaxConcurrentNum(12); 34 | heartbeatDO.setAppIp("127.0.0.1"); 35 | heartbeatDO.setStatisticsCycleTime(new Date()); 36 | dataList.add(heartbeatDO); 37 | 38 | heartbeatDO = new HeartbeatDO(); 39 | heartbeatDO.setAppGroupName("BikeBusinessDepartment"); 40 | heartbeatDO.setAppName("bh-order"); 41 | heartbeatDO.setPoint("testPoint1"); 42 | heartbeatDO.setDowngradeNum(123L); 43 | heartbeatDO.setVisitNum(1000000L); 44 | heartbeatDO.setExceptionNum(234L); 45 | heartbeatDO.setTimeoutNum(1233L); 46 | heartbeatDO.setMaxConcurrentNum(12); 47 | heartbeatDO.setAppIp("127.0.0.1"); 48 | heartbeatDO.setStatisticsCycleTime(new Date()); 49 | dataList.add(heartbeatDO); 50 | 51 | Assert.assertEquals(2, heartbeatDao.addHeartbeat(dataList)); 52 | } 53 | 54 | @Test 55 | public void queryHeartbeatListTest() { 56 | System.out.println(heartbeatDao.queryHeartbeatList("BikeBusinessDepartment", "bh-order", "testPoint", 57 | new Date(System.currentTimeMillis() - 10000000), new Date())); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/dao/PointDictDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.dao; 2 | 3 | import com.didiglobal.sds.admin.dao.PointDictDao; 4 | import com.didiglobal.sds.admin.dao.bean.PointDictDO; 5 | import org.assertj.core.util.Lists; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | /** 13 | * Created by tianyulei on 2019/7/10 14 | **/ 15 | @RunWith(SpringRunner.class) 16 | @SpringBootTest 17 | public class PointDictDaoTest { 18 | 19 | @Autowired 20 | private PointDictDao pointDictDao; 21 | 22 | @Test 23 | public void testInsert(){ 24 | PointDictDO pointDictDO = new PointDictDO(); 25 | 26 | pointDictDO.setAppName("t1"); 27 | pointDictDO.setAppGroupName("tg1"); 28 | pointDictDO.setPoint("testPointDict2"); 29 | pointDictDao.addPointDict(pointDictDO); 30 | } 31 | 32 | @Test 33 | public void testdelete(){ 34 | pointDictDao.deletePointDictList(Lists.newArrayList(442L)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/dao/PointReturnValueDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.dao; 2 | 3 | import com.didiglobal.sds.admin.dao.PointReturnValueDao; 4 | import com.didiglobal.sds.admin.dao.bean.PointReturnValueDO; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | /** 12 | * Created by manzhizhen on 18/2/14. 13 | */ 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest 16 | public class PointReturnValueDaoTest { 17 | 18 | @Autowired 19 | private PointReturnValueDao pointReturnValueDao; 20 | 21 | 22 | @Test 23 | public void addPointReturnValueTest() { 24 | 25 | PointReturnValueDO pointReturnValueDO = new PointReturnValueDO(); 26 | 27 | pointReturnValueDO.setAppGroupName("htw"); 28 | pointReturnValueDO.setAppName("测试"); 29 | pointReturnValueDO.setPoint("testPoint"); 30 | pointReturnValueDO.setStatus(1); 31 | pointReturnValueDO.setReturnValueStr("abc-json"); 32 | pointReturnValueDO.setOperatorName("manzhizhen"); 33 | pointReturnValueDO.setOperatorEmail("manzhizhen@didichuxing.com"); 34 | pointReturnValueDO.setCreatorName("manzhizhen"); 35 | pointReturnValueDO.setCreatorEmail("manzhizhen@didichuxing.com"); 36 | 37 | pointReturnValueDao.addPointReturnValue(pointReturnValueDO); 38 | } 39 | 40 | 41 | @Test 42 | public void updatePointReturnValueTest() { 43 | 44 | pointReturnValueDao.updatePointReturnValue("htw", "测试", "testPoint", 45 | "new-abc-json", 0, "manzhizhen", "manzhizhen@didichuxing.com"); 46 | } 47 | 48 | 49 | @Test 50 | public void deletePointReturnValueTest() { 51 | 52 | pointReturnValueDao.deletePointReturnValue("htw", "测试", "testPoint"); 53 | } 54 | 55 | @Test 56 | public void queryPointReturnValueByPageTest() { 57 | System.out.println( 58 | pointReturnValueDao.queryPointReturnValueByPage("hm", "yzq-dubbo1", "sdfsdf", "sdfsdf", 0, 10)); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/dao/SdsSchemeDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.dao; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.didiglobal.sds.admin.dao.SdsSchemeDao; 5 | import com.didiglobal.sds.admin.dao.bean.SdsSchemeDO; 6 | import org.junit.Assert; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | /** 14 | * Created by manzhizhen on 18/2/12. 15 | */ 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest 18 | public class SdsSchemeDaoTest { 19 | 20 | @Autowired 21 | private SdsSchemeDao sdsSchemeDao; 22 | 23 | @Test 24 | public void addSdsSchemeTest() { 25 | SdsSchemeDO sdsSchemeDO = new SdsSchemeDO(); 26 | sdsSchemeDO.setAppGroupName("BikeBusinessDepartment"); 27 | sdsSchemeDO.setAppName("bh-order"); 28 | 29 | sdsSchemeDO.setSdsSchemeName("FIRST_GROUP"); 30 | sdsSchemeDO.setCreatorName("路飞"); 31 | sdsSchemeDO.setCreatorEmail("manzhizhen@didichuxing.com"); 32 | sdsSchemeDO.setOperatorName("路飞"); 33 | sdsSchemeDO.setOperatorEmail("manzhizhen@didichuxing.com"); 34 | Assert.assertEquals(1, sdsSchemeDao.addSdsScheme(sdsSchemeDO)); 35 | 36 | sdsSchemeDO.setSdsSchemeName("SECOND_GROUP"); 37 | Assert.assertEquals(1, sdsSchemeDao.addSdsScheme(sdsSchemeDO)); 38 | } 39 | 40 | @Test 41 | public void queryAllSdsSchemeTest() { 42 | System.out.println(JSON.toJSONString(sdsSchemeDao.queryAllSdsScheme("BikeBusinessDepartment", "order"))); 43 | } 44 | 45 | @Test 46 | public void queryByGroupNameTest() { 47 | System.out.println(sdsSchemeDao.queryByGroupName("BikeBusinessDepartment", "bh-order", "FIRST_GROUP")); 48 | } 49 | 50 | @Test 51 | public void updateSdsSchemeTest() { 52 | System.out.println(sdsSchemeDao.updateSdsScheme("BikeBusinessDepartment", "bh-order", "FIRST_GROUP", "FIRST_GROUP1", "路飞", 53 | "manzhizhen@didichuxing.com")); 54 | } 55 | 56 | @Test 57 | public void deleteSdsSchemeTest() { 58 | System.out.println(sdsSchemeDao.deleteSdsScheme("BikeBusinessDepartment", "bh-order", "FIRST_GROUP")); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /sds-admin/src/test/java/com/didiglobal/sds/admin/test/service/PointDictServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.admin.test.service; 2 | 3 | import com.didiglobal.sds.client.bean.SdsCycleInfo; 4 | import com.didiglobal.sds.admin.dao.bean.PointDictDO; 5 | import com.didiglobal.sds.admin.service.PointDictService; 6 | import org.assertj.core.util.Maps; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | /** 18 | * Created by tianyulei on 2019/7/15 19 | **/ 20 | @RunWith(SpringRunner.class) 21 | @SpringBootTest 22 | public class PointDictServiceTest { 23 | 24 | @Autowired 25 | private PointDictService pointDictService; 26 | 27 | @Test 28 | public void testInsert() { 29 | PointDictDO pointDictDO = new PointDictDO(); 30 | pointDictDO.setPoint("1"); 31 | pointDictDO.setAppName("1"); 32 | pointDictDO.setAppGroupName("1"); 33 | 34 | PointDictDO pointDictDO1 = new PointDictDO(); 35 | pointDictDO1.setPoint("2"); 36 | pointDictDO1.setAppName("2"); 37 | pointDictDO1.setAppGroupName("2"); 38 | 39 | PointDictDO pointDictDO2 = new PointDictDO(); 40 | pointDictDO2.setPoint("3"); 41 | pointDictDO2.setAppName("3"); 42 | pointDictDO2.setAppGroupName("3"); 43 | 44 | PointDictDO pointDictDO3 = new PointDictDO(); 45 | pointDictDO3.setPoint("4"); 46 | pointDictDO3.setAppName("4"); 47 | pointDictDO3.setAppGroupName("4"); 48 | 49 | PointDictDO pointDictDO4 = new PointDictDO(); 50 | pointDictDO4.setPoint("4"); 51 | pointDictDO4.setAppName("4"); 52 | pointDictDO4.setAppGroupName("4"); 53 | 54 | 55 | List list = new ArrayList<>(); 56 | list.add(pointDictDO); 57 | list.add(pointDictDO1); 58 | list.add(pointDictDO2); 59 | list.add(pointDictDO3); 60 | list.add(pointDictDO4); 61 | 62 | pointDictService.addPointList(list); 63 | } 64 | 65 | @Test 66 | public void testCheckAndDelete(){ 67 | for(int i = 0; i< 11; i++){ 68 | Map map = Maps.newHashMap("1", new SdsCycleInfo()); 69 | 70 | pointDictService.checkAndDeleteDeadPoint(map, "1", "1"); 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /sds-admin/src/test/resources/config/application.properties: -------------------------------------------------------------------------------- 1 | spring.profiles.active=dev 2 | -------------------------------------------------------------------------------- /sds-admin/src/test/resources/config/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | [%-5level] %d{${DATETIME}} [%thread] %logger{36} - %m%n 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /sds-bootstrap/src/main/java/com/didiglobal/sds/bootstrap/SdsBootStrap.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.bootstrap; 2 | 3 | import com.didiglobal.sds.bootstrap.transformer.SdsClassFileTransformer; 4 | import com.didiglobal.sds.client.SdsClient; 5 | import com.didiglobal.sds.client.SdsClientFactory; 6 | import com.didiglobal.sds.client.log.SdsLoggerFactory; 7 | import org.slf4j.Logger; 8 | 9 | import java.lang.instrument.Instrumentation; 10 | 11 | /** 12 | * Created by manzhizhen on 17/3/26. 13 | */ 14 | public class SdsBootStrap { 15 | 16 | private static Logger logger = SdsLoggerFactory.getDefaultLogger(); 17 | 18 | private volatile static SdsClient client = null; 19 | 20 | private static final int BOOTSTRAP_PARAM_NUM = 4; 21 | 22 | /** 23 | * VM Options: -javaagent:/Users/manzhizhen/Documents/git/daijia-sds/sds-bootstrap/target/sds-bootstrap.jar=heima, 24 | * mzz-study,url,com.manzhizhen 25 | * 26 | * @param agentArgs 27 | * @param instrumentation 28 | */ 29 | public static void premain(String agentArgs, Instrumentation instrumentation) { 30 | 31 | if (agentArgs == null) { 32 | agentArgs = ""; 33 | } 34 | 35 | logger.info("Sds agentArgs:" + agentArgs); 36 | 37 | String[] param = agentArgs.split(","); 38 | 39 | /** 40 | * 参数1:应用组名称 41 | * 参数2:应用名称 42 | * 参数3:sds服务端url 43 | * 参数4:需要sds扫描的包路径 44 | */ 45 | if (param.length != BOOTSTRAP_PARAM_NUM) { 46 | logger.error("Sds agentArgs num not 4:" + agentArgs); 47 | return; 48 | } 49 | 50 | client = SdsClientFactory.getOrCreateSdsClient(param[0], param[1], param[2]); 51 | 52 | logger.info("sdsClient: " + client); 53 | 54 | instrumentation.addTransformer(new SdsClassFileTransformer(param[3])); 55 | 56 | } 57 | 58 | public static SdsClient getClient() { 59 | return client; 60 | } 61 | 62 | private static String getClassPathFromSystemProperty() { 63 | return System.getProperty("java.class.path"); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sds-client/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /sds-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | com.didiglobal.sds 6 | sds-base 7 | ${revision} 8 | ../pom.xml 9 | 10 | 11 | 4.0.0 12 | 13 | com.didiglobal.sds 14 | sds-client 15 | 16 | sds-client 17 | 18 | https://github.com/didi/sds 19 | 20 | 21 | 22 | com.alibaba 23 | fastjson 24 | 25 | 26 | org.slf4j 27 | slf4j-api 28 | 29 | 30 | 31 | 32 | org.slf4j 33 | slf4j-log4j12 34 | test 35 | 36 | 37 | junit 38 | junit 39 | test 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.apache.maven.plugins 47 | maven-gpg-plugin 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/AbstractSdsClient.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client; 2 | 3 | public abstract class AbstractSdsClient implements SdsClient { 4 | 5 | protected String appGroupName; 6 | 7 | protected String appName; 8 | 9 | protected String serverAddrList; 10 | 11 | public AbstractSdsClient(String appGroupName, String appName, String serverAddrList) { 12 | this.appGroupName = appGroupName; 13 | this.appName = appName; 14 | this.serverAddrList = serverAddrList; 15 | } 16 | 17 | public String getAppGroupName() { 18 | return appGroupName; 19 | } 20 | 21 | public String getAppName() { 22 | return appName; 23 | } 24 | 25 | public String getServerAddrList() { 26 | return serverAddrList; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | final StringBuilder sb = new StringBuilder("AbstractSdsClient{"); 32 | sb.append("appGroupName='").append(appGroupName).append('\''); 33 | sb.append(", appName='").append(appName).append('\''); 34 | sb.append(", serverAddrList='").append(serverAddrList).append('\''); 35 | sb.append('}'); 36 | return sb.toString(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/SdsClient.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client; 2 | 3 | /** 4 | * 服务降级的客户端api 5 | *

6 | * Created by manzhizhen on 17/1/1. 7 | */ 8 | public interface SdsClient { 9 | 10 | /** 11 | * 该请求是否需要降级 12 | * 13 | * @param point 降级点名称,每个应用内必须唯一 14 | * @return false-不需要降级,正常访问; true-需要降级 15 | */ 16 | boolean shouldDowngrade(String point); 17 | 18 | /** 19 | * 用来标记业务处理时抛出的异常 20 | * 在需要使用异常率/异常量降级时需要用此方法来统计异常次数 21 | * 22 | * @param point 降级点名称 23 | * @param exception 业务处理时抛出的异常,如果不关心异常类型,该参数可以传null 24 | */ 25 | void exceptionSign(String point, Throwable exception); 26 | 27 | /** 28 | * 退出降级逻辑 29 | * 该方法需要写到finally代码块中 30 | * 31 | * @param point 降级点名称 32 | */ 33 | void downgradeFinally(String point); 34 | } 35 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/annotation/SdsDowngradeMethod.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kuaidadi.com Inc. 3 | * Copyright (c) 2012-2016 All Rights Reserved. 4 | */ 5 | package com.didiglobal.sds.client.annotation; 6 | 7 | import java.lang.annotation.*; 8 | 9 | /** 10 | * 服务降级方法注解 11 | * 12 | * @author manzhizhen 13 | * @version $Id: SdsDowngradeMethod.java, v 0.1 2016年1月9日 上午10:43:45 Administrator Exp $ 14 | */ 15 | @Target({ ElementType.METHOD }) 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Documented 18 | public @interface SdsDowngradeMethod { 19 | 20 | /** 21 | * 降级点 22 | */ 23 | String point(); 24 | 25 | /** 26 | * 异常类型 27 | */ 28 | Class exceptionClass() default Exception.class; 29 | 30 | /** 31 | * 出现异常后的降级方法名称,和使用注解标注的方法在同一个类中,注意这里有降级的优先级顺序 32 | * fallback 指定的方法 > sds-admin 配置的策略 > 默认(抛出异常) 33 | * 34 | * @return 方法名称 35 | */ 36 | String fallback() default ""; 37 | } 38 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/annotation/SdsStrategyExecutor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kuaidadi.com Inc. 3 | * Copyright (c) 2012-2016 All Rights Reserved. 4 | */ 5 | package com.didiglobal.sds.client.annotation; 6 | 7 | import java.lang.annotation.*; 8 | 9 | /** 10 | * 服务降级方法注解 11 | * 12 | * 13 | * @author manzhizhen 14 | * @version $Id: SdsDowngradeMethod.java, v 0.1 2016年1月9日 上午10:43:45 Administrator Exp $ 15 | */ 16 | @Target({ ElementType.TYPE }) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | @Documented 19 | public @interface SdsStrategyExecutor { 20 | 21 | /** 22 | * 策略执行顺序,取值0~Integer.MAX_VALUE,越小就越先执行 23 | */ 24 | int sort(); 25 | } 26 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/bean/SdsClassDefine.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kuaidadi.com Inc. 3 | * Copyright (c) 2012-2016 All Rights Reserved. 4 | */ 5 | package com.didiglobal.sds.client.bean; 6 | 7 | /** 8 | * 简单类定义实体 9 | * 10 | * @author manzhizhen 11 | * @version $Id: SdsClassDefine.java, v 0.1 2016年1月10日 上午11:13:31 Administrator Exp $ 12 | */ 13 | public class SdsClassDefine { 14 | 15 | /** 16 | * 类全限定名 17 | */ 18 | private String fullName; 19 | 20 | public String getFullName() { 21 | return fullName; 22 | } 23 | 24 | public void setFullName(String fullName) { 25 | this.fullName = fullName; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/bean/SdsCycleInfo.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.bean; 2 | 3 | /** 4 | * Created by manzhizhen on 17/3/5. 5 | */ 6 | public class SdsCycleInfo { 7 | 8 | /** 9 | * 降级点名称 10 | */ 11 | private String point; 12 | 13 | /** 14 | * 周期访问量 15 | */ 16 | private Long visitNum; 17 | 18 | /** 19 | * 周期异常数 20 | */ 21 | private Long exceptionNum; 22 | 23 | /** 24 | * 周期最高并发量 25 | */ 26 | private Integer concurrentNum; 27 | 28 | /** 29 | * 周期超时量 30 | */ 31 | private Long timeoutNum; 32 | 33 | /** 34 | * 周期降级总量 35 | */ 36 | private Long downgradeNum; 37 | 38 | public String getPoint() { 39 | return point; 40 | } 41 | 42 | public void setPoint(String point) { 43 | this.point = point; 44 | } 45 | 46 | public Long getVisitNum() { 47 | return visitNum; 48 | } 49 | 50 | public void setVisitNum(Long visitNum) { 51 | this.visitNum = visitNum; 52 | } 53 | 54 | public Long getExceptionNum() { 55 | return exceptionNum; 56 | } 57 | 58 | public void setExceptionNum(Long exceptionNum) { 59 | this.exceptionNum = exceptionNum; 60 | } 61 | 62 | public Integer getConcurrentNum() { 63 | return concurrentNum; 64 | } 65 | 66 | public void setConcurrentNum(Integer concurrentNum) { 67 | this.concurrentNum = concurrentNum; 68 | } 69 | 70 | public Long getTimeoutNum() { 71 | return timeoutNum; 72 | } 73 | 74 | public void setTimeoutNum(Long timeoutNum) { 75 | this.timeoutNum = timeoutNum; 76 | } 77 | 78 | public Long getDowngradeNum() { 79 | return downgradeNum; 80 | } 81 | 82 | public void setDowngradeNum(Long downgradeNum) { 83 | this.downgradeNum = downgradeNum; 84 | } 85 | 86 | @Override 87 | public String toString() { 88 | final StringBuilder sb = new StringBuilder("SdsCycleInfo{"); 89 | sb.append("point='").append(point).append('\''); 90 | sb.append(", visitNum=").append(visitNum); 91 | sb.append(", exceptionNum=").append(exceptionNum); 92 | sb.append(", concurrentNum=").append(concurrentNum); 93 | sb.append(", timeoutNum=").append(timeoutNum); 94 | sb.append(", downgradeNum=").append(downgradeNum); 95 | sb.append('}'); 96 | return sb.toString(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/bean/VisitWrapperValue.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.bean; 2 | 3 | /** 4 | * 访问量的包装值 5 | * 包含当前桶值和当前的滑动周期值 6 | * 7 | * Created by manzhizhen on 18/2/24. 8 | */ 9 | public class VisitWrapperValue { 10 | /** 11 | * 当前桶值 12 | */ 13 | private long bucketValue; 14 | 15 | /** 16 | * 滑动周期值 17 | */ 18 | private long slidingCycleValue; 19 | 20 | public VisitWrapperValue(long bucketValue, long slidingCycleValue) { 21 | this.bucketValue = bucketValue; 22 | this.slidingCycleValue = slidingCycleValue; 23 | } 24 | 25 | public long getBucketValue() { 26 | return bucketValue; 27 | } 28 | 29 | public long getSlidingCycleValue() { 30 | return slidingCycleValue; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | final StringBuilder sb = new StringBuilder("VisitWrapperValue{"); 36 | sb.append("bucketValue=").append(bucketValue); 37 | sb.append(", slidingCycleValue=").append(slidingCycleValue); 38 | sb.append('}'); 39 | return sb.toString(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/config/SdsPointReturnValueConfig.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.config; 2 | 3 | /** 4 | * 降级点返回值配置 5 | * 6 | * @author manzhizhen 7 | * @date 2019-04-21 8 | */ 9 | public class SdsPointReturnValueConfig { 10 | 11 | /** 12 | * 设置某个降级点降级后的返回值 13 | * 14 | * 优先级:服务端配置id优先级高于此方法设置的返回值的返回值 15 | * 16 | * @param point 17 | * @param returnValue 18 | */ 19 | public static void setPointDowngradeReturnValue(String point, Object returnValue) { 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/config/SdsPointStrategyConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kuaidadi.com Inc. 3 | * Copyright (c) 2012-2016 All Rights Reserved. 4 | */ 5 | package com.didiglobal.sds.client.config; 6 | 7 | import com.didiglobal.sds.client.service.SdsDowngradeDelayService; 8 | import com.didiglobal.sds.client.service.SdsDowngradeExceptionService; 9 | import com.didiglobal.sds.client.util.AssertUtil; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * 降级点策略配置 16 | * 17 | * @author manzhizhen 18 | */ 19 | public class SdsPointStrategyConfig { 20 | 21 | /** 22 | * 给降级点设置降级延迟时间 23 | * 24 | * @param point 降级点名称 25 | * @param delayTime 降级延迟时间,单位毫秒 26 | * 27 | */ 28 | public static void setDowngradeDelay(String point, long delayTime) { 29 | AssertUtil.notBlack(point, "降级点不能为空!"); 30 | 31 | SdsDowngradeDelayService.getInstance().addPointDelay(point, delayTime); 32 | } 33 | 34 | /** 35 | * 给降级点设置降级延迟时间 36 | * 37 | * @param point 降级点名称 38 | * @param delayTime 降级延迟时间,单位毫秒 39 | * @param retryInterval 降级延迟重试时间间隔,单位毫秒,小于等于0表示不重试 40 | */ 41 | public static void setDowngradeDelay(String point, long delayTime, long retryInterval) { 42 | AssertUtil.notBlack(point, "降级点不能为空!"); 43 | 44 | SdsDowngradeDelayService.getInstance().addPointDelay(point, delayTime, retryInterval); 45 | } 46 | 47 | /** 48 | * 给降级点设置降级异常 49 | * 50 | * @param point 降级点 51 | * @param exceptions 属于失败请求的异常 52 | */ 53 | public static void setDowngradeExceptions(String point, List> exceptions) { 54 | AssertUtil.notBlack(point, "降级点不能为空!"); 55 | 56 | SdsDowngradeExceptionService.getInstance().addPointException(point, exceptions, new ArrayList>()); 57 | } 58 | 59 | /** 60 | * 给降级点设置排除降级异常 61 | * 62 | * @param point 降级点 63 | * @param exceptExceptions 不属于失败请求的异常 64 | */ 65 | public static void setDowngradeExceptExceptions(String point, List> exceptExceptions) { 66 | AssertUtil.notBlack(point, "降级点不能为空!"); 67 | 68 | SdsDowngradeExceptionService.getInstance() 69 | .addPointException(point, new ArrayList>(), exceptExceptions); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/contant/BizConstant.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.contant; 2 | 3 | /** 4 | * Created by manzhizhen on 17/6/23. 5 | */ 6 | final public class BizConstant { 7 | 8 | /** 9 | * 每个桶的时间,单位秒 10 | */ 11 | public static final int BUCKET_TIME = 1; 12 | 13 | /** 14 | * 每个(统计)周期内的桶数量 15 | * 注意,该值应该是10的整数倍并且能被60整除,这样比较合理,所以目前只能取值10、20、30 16 | * 并且:每个桶的时间固定,为1秒钟 17 | */ 18 | public static final int CYCLE_BUCKET_NUM = 10; 19 | 20 | /** 21 | * 周期数量,为了上传统计数据方便,内存中保存上一个周期和当前周期的数据,并为下一个周期预留空间,所以是3个周期 22 | */ 23 | public static final int CYCLE_NUM = 3; 24 | 25 | /** 26 | * 1秒内的毫秒数 27 | */ 28 | public static final long MILLISECOND_IN_SECOND = 1000; 29 | 30 | /** 31 | * 应用组名称 32 | */ 33 | public static final String APP_GROUP_NAME = "sds.app.group.name"; 34 | 35 | /** 36 | * 应用名称 37 | */ 38 | public static final String APP_NAME = "sds.app.name"; 39 | 40 | /** 41 | * 服务端地址列表,如果是多个地址,那么用英文","隔开 42 | */ 43 | public static final String SERVER_ADDR_LIST = "sds.server.addr.list"; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/contant/ExceptionCode.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.contant; 2 | 3 | /** 4 | * Created by manzhizhen on 17/5/1. 5 | */ 6 | public enum ExceptionCode { 7 | DOWNGRADE(1, "此请求已经被降级"); 8 | 9 | 10 | private int code; 11 | private String msg; 12 | 13 | ExceptionCode(int code, String msg) { 14 | this.code = code; 15 | this.msg = msg; 16 | } 17 | 18 | public int getCode() { 19 | return code; 20 | } 21 | 22 | public String getMsg() { 23 | return msg; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/counter/AbstractCycleData.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.counter; 2 | 3 | import com.didiglobal.sds.client.bean.VisitWrapperValue; 4 | 5 | /** 6 | * 抽象周期数据类 7 | *

8 | * 完整周期(WholeCycle): 包含桶indxe0-9或者10-19或者20-29这10个桶的周期就是完整的周期。上传统计和降级的数据都来自一个完整周期。 9 | * 滑动周期(SlidingCycle):从当前时间算出的当前桶index,然后往前推9个桶,这10个桶组成的周期就是滑动周期。判断要不要降级是根据当前的滑动周期的数据来的。 10 | *

11 | * Created by manzhizhen on 17/7/23. 12 | */ 13 | public abstract class AbstractCycleData { 14 | 15 | /** 16 | * 时间对应的桶值新增1 17 | * 18 | * @param time 19 | * @return 20 | */ 21 | abstract public VisitWrapperValue incrementAndGet(long time); 22 | 23 | /** 24 | * 设置对应时间的桶的值 25 | * 26 | * @param time 27 | * @param value 28 | * @return 29 | */ 30 | abstract public void setBucketValue(long time, Long value); 31 | 32 | /** 33 | * 获取时间对应的桶值 34 | * 35 | * @param time 36 | * @return 37 | */ 38 | abstract public long getBucketValue(long time); 39 | 40 | /** 41 | * 获取当前时间所处【滑动周期】的统计值 42 | * 43 | * @param time 当前毫秒数 44 | * @return 45 | */ 46 | abstract public long getCurSlidingCycleValue(long time); 47 | 48 | /** 49 | * 获取当前时间所处周期的上个【完整周期】所有桶的总值 50 | * 51 | * @param time 当前毫秒数 52 | * @return 53 | */ 54 | abstract public long getLastWholeCycleValue(long time); 55 | 56 | /** 57 | * 清理当前时间所处周期的下个完整周期的数据 58 | * 59 | * @param time 当前毫秒数 60 | * @return 61 | */ 62 | abstract public void clearNextCycleValue(long time); 63 | } 64 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/counter/TokenBucketData.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.counter; 2 | 3 | import com.didiglobal.sds.client.bean.VisitWrapperValue; 4 | import com.didiglobal.sds.client.contant.BizConstant; 5 | 6 | /** 7 | * 令牌桶的实现类(可以认为是QPS的高级替换方案) 8 | * 速率:每秒生成多少个令牌 9 | * 桶容量:桶里面最多能存储多少个令牌 10 | * 11 | * @auther manzhizhen 12 | * @date 2018/12/31 13 | */ 14 | public class TokenBucketData { 15 | 16 | /** 17 | * 每个1秒能生成多少个令牌,-1表示不生效 18 | */ 19 | private Integer generatedTokensInSecond = -1; 20 | 21 | /** 22 | * 桶最多能存储多少令牌,-1表示不生效 23 | */ 24 | private Integer bucketSize = -1; 25 | 26 | /** 27 | * 主要用来统计数据 28 | */ 29 | private AbstractCycleData cycleTokenBucketData = new SlidingWindowData(BizConstant.CYCLE_NUM, 30 | BizConstant.CYCLE_BUCKET_NUM, BizConstant.BUCKET_TIME); 31 | 32 | public TokenBucketData(Integer generatedTokensInSecond, Integer bucketSize) { 33 | this.generatedTokensInSecond = generatedTokensInSecond; 34 | this.bucketSize = bucketSize; 35 | } 36 | 37 | public TokenBucketData() { 38 | } 39 | 40 | /** 41 | * 当前秒令牌使用计数器+1 42 | * 43 | * @param time 44 | * @return 45 | */ 46 | public long takeOneToken(long time) { 47 | 48 | VisitWrapperValue visitWrapperValue = cycleTokenBucketData.incrementAndGet(time); 49 | 50 | return visitWrapperValue.getBucketValue(); 51 | } 52 | 53 | public AbstractCycleData getCycleTokenBucketData() { 54 | return cycleTokenBucketData; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/enums/DowngradeActionType.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.enums; 2 | 3 | public enum DowngradeActionType { 4 | VISIT(1, "访问量策略"), CONCURRENT(2, "并发策略"), EXCEPTION(3, "异常量策略"), EXCEPTION_RATE(4, "异常率策略"), TIMEOUT(5, "超时策略"), 5 | TOKEN_BUCKET(6, "令牌桶策略"), PRESSURE_TEST(7, "压测策略"); 6 | 7 | private int type; 8 | 9 | private String desc; 10 | 11 | DowngradeActionType(int type, String desc) { 12 | this.type = type; 13 | this.desc = desc; 14 | } 15 | 16 | @Override 17 | public String toString() { 18 | final StringBuilder sb = new StringBuilder("DowngradeActionType{"); 19 | sb.append("type=").append(type); 20 | sb.append(", desc='").append(desc).append('\''); 21 | sb.append('}'); 22 | return sb.toString(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/exception/SdsException.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.exception; 2 | 3 | import com.didiglobal.sds.client.contant.ExceptionCode; 4 | 5 | import static com.didiglobal.sds.client.contant.ExceptionCode.DOWNGRADE; 6 | 7 | /** 8 | * 降级后抛的异常 9 | *

10 | * Created by manzhizhen on 17/5/1. 11 | */ 12 | public class SdsException extends RuntimeException { 13 | 14 | private String point; 15 | 16 | private int code = DOWNGRADE.getCode(); 17 | 18 | private String msg = DOWNGRADE.getMsg(); 19 | 20 | public SdsException() { 21 | super(DOWNGRADE.getMsg()); 22 | } 23 | 24 | public SdsException(String point, int code, String msg) { 25 | super(msg); 26 | 27 | this.point = point; 28 | this.code = code; 29 | this.msg = msg; 30 | } 31 | 32 | public SdsException(int code, String msg) { 33 | super(msg); 34 | 35 | this.code = code; 36 | this.msg = msg; 37 | } 38 | 39 | public SdsException(String point) { 40 | super(DOWNGRADE.getMsg()); 41 | 42 | this.point = point; 43 | } 44 | 45 | public SdsException(ExceptionCode downgrade) { 46 | super(downgrade.getMsg()); 47 | 48 | this.code = downgrade.getCode(); 49 | this.msg = downgrade.getMsg(); 50 | } 51 | 52 | public SdsException(String point, ExceptionCode downgrade) { 53 | super(downgrade.getMsg()); 54 | 55 | this.point = point; 56 | this.code = downgrade.getCode(); 57 | this.msg = downgrade.getMsg(); 58 | } 59 | 60 | 61 | public String getPoint() { 62 | return point; 63 | } 64 | 65 | public void setPoint(String point) { 66 | this.point = point; 67 | } 68 | 69 | public Integer getCode() { 70 | return code; 71 | } 72 | 73 | public void setCode(Integer code) { 74 | this.code = code; 75 | } 76 | 77 | public String getMsg() { 78 | return msg; 79 | } 80 | 81 | public void setMsg(String msg) { 82 | this.msg = msg; 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | final StringBuilder sb = new StringBuilder("SdsException{"); 88 | sb.append("point='").append(point).append('\''); 89 | sb.append(", code=").append(code); 90 | sb.append(", msg='").append(msg).append('\''); 91 | sb.append('}'); 92 | return sb.toString(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/listener/DowngradeActionListener.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.listener; 2 | 3 | import com.didiglobal.sds.client.enums.DowngradeActionType; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * 降级动作监听器 9 | */ 10 | public interface DowngradeActionListener { 11 | 12 | /** 13 | * 触发降级事件 14 | * 15 | * @param point 16 | * @param downgradeActionType 17 | * @param time 18 | */ 19 | void downgradeAction(String point, DowngradeActionType downgradeActionType, Date time); 20 | } 21 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/log/SdsLoggerConstants.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.didiglobal.sds.client.log; 5 | 6 | /** 7 | * 日志常量 8 | * 9 | * @author manzhizhen 10 | * @version $Id: SdsLoggerConstants.java, v 0.1 2016年2月21日 上午10:36:36 Administrator Exp $ 11 | */ 12 | public class SdsLoggerConstants { 13 | 14 | public static final String DEFAULT_LOGGER_NAME = "sdsLogger"; 15 | 16 | public static final String HEARTBEAT_LOGGER_NAME = "heartbeatLogger"; 17 | 18 | public static final String PULL_STRATEGY_LOGGER_NAME = "pullStrategyLogger"; 19 | } 20 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/log/SdsLoggerFactory.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.log; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * 客户端日志 8 | * 9 | * @author manzhizhen 10 | * @version $Id: ServerBizLogger.java, v 0.1 2015年9月22日 上午10:07:27 Administrator Exp $ 11 | */ 12 | public class SdsLoggerFactory { 13 | 14 | /** 15 | * 返回api正常业务日志 16 | */ 17 | public static Logger getDefaultLogger() { 18 | return LoggerFactory.getLogger(SdsLoggerConstants.DEFAULT_LOGGER_NAME); 19 | } 20 | 21 | /** 22 | * 返回心跳日志 23 | */ 24 | public static Logger getHeartbeatLogger() { 25 | return LoggerFactory.getLogger(SdsLoggerConstants.HEARTBEAT_LOGGER_NAME); 26 | } 27 | 28 | /** 29 | * 返回拉取策略日志 30 | */ 31 | public static Logger getPullStrategyLogger() { 32 | return LoggerFactory.getLogger(SdsLoggerConstants.PULL_STRATEGY_LOGGER_NAME); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/service/SdsTimeoutService.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.service; 2 | 3 | /** 4 | * Created by manzhizhen on 2016/6/22. 5 | */ 6 | public class SdsTimeoutService { 7 | 8 | private static SdsTimeoutService sdsTimeoutService = new SdsTimeoutService(); 9 | 10 | private SdsTimeoutService() {} 11 | 12 | public static SdsTimeoutService getInstance() { 13 | return sdsTimeoutService; 14 | } 15 | 16 | 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/strategy/DefaultStrategyExecutorBuilder.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.strategy; 2 | 3 | import com.didiglobal.sds.client.strategy.executor.*; 4 | 5 | /** 6 | *

description : DefaultStrategyExecutorBuilder 7 | * 8 | * @author : masteryourself 9 | * @version : 1.0.1 10 | * @date : 2020/3/14 11:52 11 | */ 12 | public class DefaultStrategyExecutorBuilder implements StrategyExecutorBuilder { 13 | 14 | @Override 15 | public AbstractStrategyExecutor build() { 16 | return new VisitStrategyExecutor( 17 | new TokenBucketStrategyExecutor( 18 | new ConcurrentStrategyExecutor( 19 | new TimeoutStrategyExecutor( 20 | new ExceptionStrategyExecutor( 21 | new ExceptionRateStrategyExecutor(null) 22 | ))))); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/strategy/StrategyExecutorBuilder.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.strategy; 2 | 3 | import com.didiglobal.sds.client.strategy.executor.AbstractStrategyExecutor; 4 | 5 | /** 6 | *

description : StrategyExecutorBuilder 7 | * 8 | * @author : masteryourself 9 | * @version : 1.0.1 10 | * @date : 2020/3/14 11:43 11 | */ 12 | public interface StrategyExecutorBuilder { 13 | 14 | /** 15 | * 构建策略链 16 | * 17 | * @return AbstractStrategyExecutor 链条 18 | */ 19 | AbstractStrategyExecutor build(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/strategy/executor/AbstractStrategyExecutor.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.strategy.executor; 2 | 3 | import com.didiglobal.sds.client.bean.CheckData; 4 | import com.didiglobal.sds.client.bean.SdsStrategy; 5 | import com.didiglobal.sds.client.enums.DowngradeActionType; 6 | 7 | /** 8 | * Created by manzhizhen on 17/7/26. 9 | */ 10 | public abstract class AbstractStrategyExecutor { 11 | 12 | protected AbstractStrategyExecutor next; 13 | 14 | public AbstractStrategyExecutor(AbstractStrategyExecutor next) { 15 | this.next = next; 16 | } 17 | 18 | /** 19 | * 策略检查 20 | * 21 | * @param checkData 当前数据 22 | * @param strategy 当前策略 23 | * @return true: 通过,不用降级; false:不通过,需要降级 24 | */ 25 | protected abstract boolean strategyCheck(CheckData checkData, SdsStrategy strategy); 26 | 27 | /** 28 | * 获取策略类型 29 | * 30 | * @return true: 通过,不用降级; false:不通过,需要降级 31 | */ 32 | protected abstract DowngradeActionType getStrategyType(); 33 | 34 | /** 35 | * 开始执行策略(链) 36 | * 37 | * @param checkData 38 | * @param strategy 39 | * @return 降级检查结果,null-通过检查,不用降级,DowngradeActionType:没通过,降级触发的类型 40 | */ 41 | public DowngradeActionType execute(CheckData checkData, SdsStrategy strategy) { 42 | boolean checkSuccess = strategyCheck(checkData, strategy); 43 | 44 | if (checkSuccess && next != null) { 45 | return next.execute(checkData, strategy); 46 | } 47 | 48 | if (!checkSuccess) { 49 | return getStrategyType(); 50 | } 51 | 52 | return null; 53 | } 54 | 55 | public AbstractStrategyExecutor getNext() { 56 | return next; 57 | } 58 | 59 | public void setNext(AbstractStrategyExecutor next) { 60 | this.next = next; 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/strategy/executor/ConcurrentStrategyExecutor.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.strategy.executor; 2 | 3 | import com.didiglobal.sds.client.annotation.SdsStrategyExecutor; 4 | import com.didiglobal.sds.client.bean.CheckData; 5 | import com.didiglobal.sds.client.bean.SdsStrategy; 6 | import com.didiglobal.sds.client.enums.DowngradeActionType; 7 | 8 | /** 9 | * Created by manzhizhen on 17/7/26. 10 | */ 11 | @SdsStrategyExecutor(sort = 300) 12 | public class ConcurrentStrategyExecutor extends AbstractStrategyExecutor { 13 | 14 | public ConcurrentStrategyExecutor(AbstractStrategyExecutor next) { 15 | super(next); 16 | } 17 | 18 | @Override 19 | protected boolean strategyCheck(CheckData checkData, SdsStrategy strategy) { 20 | 21 | if(checkData.getConcurrentAcquire() == null) { 22 | return true; 23 | } 24 | 25 | /** 26 | * 由于并发策略使用了信号量,所以在统计的同时已经起到了策略判断的功能,所以这里直接返回判断结果 27 | */ 28 | return checkData.getConcurrentAcquire(); 29 | } 30 | 31 | @Override 32 | protected DowngradeActionType getStrategyType() { 33 | return DowngradeActionType.CONCURRENT; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/strategy/executor/ExceptionRateStrategyExecutor.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.strategy.executor; 2 | 3 | import com.didiglobal.sds.client.annotation.SdsStrategyExecutor; 4 | import com.didiglobal.sds.client.bean.CheckData; 5 | import com.didiglobal.sds.client.bean.SdsStrategy; 6 | import com.didiglobal.sds.client.enums.DowngradeActionType; 7 | 8 | /** 9 | * Created by manzhizhen on 17/7/26. 10 | */ 11 | @SdsStrategyExecutor(sort = 600) 12 | public class ExceptionRateStrategyExecutor extends AbstractStrategyExecutor { 13 | 14 | public ExceptionRateStrategyExecutor(AbstractStrategyExecutor next) { 15 | super(next); 16 | } 17 | 18 | @Override 19 | protected boolean strategyCheck(CheckData checkData, SdsStrategy strategy) { 20 | if (strategy.getExceptionRateStart() == null || strategy.getExceptionRateStart() < 0 || 21 | strategy.getExceptionRateThreshold() == null || strategy.getExceptionRateThreshold() < 0 || 22 | strategy.getExceptionRateThreshold() > 100 || 23 | strategy.getExceptionRateStart() >= checkData.getVisitCount()) { 24 | return true; 25 | } 26 | 27 | // 注意,在计算异常率时,分母不能直接使用访问量,需要把降级数量移除,因为降级后实际没有真正访问业务方法,不把降级数量移除将导致计算的异常率偏小 28 | long inputTotal = checkData.getVisitCount() - checkData.getDowngradeCount(); 29 | 30 | return inputTotal == 0 || (checkData.getExceptionCount() + 0.0) * 100 / inputTotal < strategy.getExceptionRateThreshold(); 31 | } 32 | 33 | @Override 34 | protected DowngradeActionType getStrategyType() { 35 | return DowngradeActionType.EXCEPTION_RATE; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/strategy/executor/ExceptionStrategyExecutor.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.strategy.executor; 2 | 3 | import com.didiglobal.sds.client.annotation.SdsStrategyExecutor; 4 | import com.didiglobal.sds.client.bean.CheckData; 5 | import com.didiglobal.sds.client.bean.SdsStrategy; 6 | import com.didiglobal.sds.client.enums.DowngradeActionType; 7 | 8 | /** 9 | * Created by manzhizhen on 17/7/26. 10 | */ 11 | @SdsStrategyExecutor(sort = 500) 12 | public class ExceptionStrategyExecutor extends AbstractStrategyExecutor { 13 | 14 | public ExceptionStrategyExecutor(AbstractStrategyExecutor next) { 15 | super(next); 16 | } 17 | 18 | @Override 19 | protected boolean strategyCheck(CheckData checkData, SdsStrategy strategy) { 20 | if (strategy.getExceptionThreshold() == null || strategy.getExceptionThreshold() < 0) { 21 | return true; 22 | } 23 | 24 | return checkData.getExceptionCount() < strategy.getExceptionThreshold(); 25 | } 26 | 27 | @Override 28 | protected DowngradeActionType getStrategyType() { 29 | return DowngradeActionType.EXCEPTION; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/strategy/executor/TimeoutStrategyExecutor.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.strategy.executor; 2 | 3 | import com.didiglobal.sds.client.annotation.SdsStrategyExecutor; 4 | import com.didiglobal.sds.client.bean.CheckData; 5 | import com.didiglobal.sds.client.bean.SdsStrategy; 6 | import com.didiglobal.sds.client.enums.DowngradeActionType; 7 | 8 | /** 9 | * Created by manzhizhen on 17/7/26. 10 | */ 11 | @SdsStrategyExecutor(sort = 400) 12 | public class TimeoutStrategyExecutor extends AbstractStrategyExecutor { 13 | 14 | public TimeoutStrategyExecutor(AbstractStrategyExecutor next) { 15 | super(next); 16 | } 17 | 18 | @Override 19 | public boolean strategyCheck(CheckData checkData, SdsStrategy strategy) { 20 | if (strategy.getTimeoutCountThreshold() == null || strategy.getTimeoutCountThreshold() < 0) { 21 | return true; 22 | } 23 | 24 | return checkData.getTimeoutCount() < strategy.getTimeoutCountThreshold(); 25 | } 26 | 27 | @Override 28 | protected DowngradeActionType getStrategyType() { 29 | return DowngradeActionType.TIMEOUT; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/strategy/executor/TokenBucketStrategyExecutor.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.strategy.executor; 2 | 3 | import com.didiglobal.sds.client.bean.CheckData; 4 | import com.didiglobal.sds.client.bean.SdsStrategy; 5 | import com.didiglobal.sds.client.enums.DowngradeActionType; 6 | 7 | import static com.didiglobal.sds.client.contant.BizConstant.BUCKET_TIME; 8 | import static com.didiglobal.sds.client.contant.BizConstant.CYCLE_BUCKET_NUM; 9 | import static com.didiglobal.sds.client.enums.DowngradeActionType.TOKEN_BUCKET; 10 | 11 | /** 12 | * 令牌桶策略执行器 13 | * 14 | * @auther manzhizhen 15 | * @date 2018/12/31 16 | */ 17 | public class TokenBucketStrategyExecutor extends AbstractStrategyExecutor { 18 | 19 | public TokenBucketStrategyExecutor(AbstractStrategyExecutor next) { 20 | super(next); 21 | } 22 | 23 | @Override 24 | protected boolean strategyCheck(CheckData checkData, SdsStrategy strategy) { 25 | if (strategy.getTokenBucketGeneratedTokensInSecond() == null || strategy. 26 | getTokenBucketGeneratedTokensInSecond() < 0) { 27 | return true; 28 | } 29 | 30 | // 如果当前桶的令牌还没用完,那么直接返回 31 | if (checkData.getTakeTokenBucketNum() <= strategy.getTokenBucketGeneratedTokensInSecond()) { 32 | return true; 33 | } 34 | 35 | // 如果当前桶的令牌已经用完,但又没额外设置桶容量(即默认桶容量和桶每秒生成的令牌数相同),那就直接拒绝 36 | if (strategy.getTokenBucketSize() <= strategy.getTokenBucketGeneratedTokensInSecond()) { 37 | return false; 38 | } 39 | 40 | // 每个桶可用的令牌数不能超过桶容量 41 | if (checkData.getTakeTokenBucketNum() > strategy.getTokenBucketSize()) { 42 | return false; 43 | } 44 | 45 | // 如果当前秒的令牌已经不够用,那么就看历史桶中是否有剩余令牌能匀一下 46 | return CYCLE_BUCKET_NUM * BUCKET_TIME * strategy.getTokenBucketGeneratedTokensInSecond() - checkData.getTakeTokenBucketNum() 47 | + checkData.getDowngradeCount() > 0; 48 | } 49 | 50 | @Override 51 | protected DowngradeActionType getStrategyType() { 52 | return TOKEN_BUCKET; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/strategy/executor/VisitStrategyExecutor.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.strategy.executor; 2 | 3 | import com.didiglobal.sds.client.annotation.SdsStrategyExecutor; 4 | import com.didiglobal.sds.client.bean.CheckData; 5 | import com.didiglobal.sds.client.bean.SdsStrategy; 6 | import com.didiglobal.sds.client.enums.DowngradeActionType; 7 | 8 | /** 9 | * Created by manzhizhen on 17/7/26. 10 | */ 11 | @SdsStrategyExecutor(sort = 100) 12 | public class VisitStrategyExecutor extends AbstractStrategyExecutor { 13 | 14 | public VisitStrategyExecutor(AbstractStrategyExecutor next) { 15 | super(next); 16 | } 17 | 18 | @Override 19 | public boolean strategyCheck(CheckData checkData, SdsStrategy strategy) { 20 | 21 | if (strategy.getVisitThreshold() == null || strategy.getVisitThreshold() < 0) { 22 | return true; 23 | } 24 | 25 | // 注意,这里一定要将降级量减去,否则一旦流量大于访问量阈值,将一直被降级下去 26 | return (checkData.getVisitCount() - checkData.getDowngradeCount()) <= strategy.getVisitThreshold(); 27 | } 28 | 29 | @Override 30 | protected DowngradeActionType getStrategyType() { 31 | return DowngradeActionType.VISIT; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/util/AssertUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kuaidadi.com Inc. 3 | * Copyright (c) 2012-2016 All Rights Reserved. 4 | */ 5 | package com.didiglobal.sds.client.util; 6 | 7 | /** 8 | * 参数断言 9 | * 10 | * @author manzhizhen 11 | * @version $Id: AssertUtil.java, v 0.1 2016年1月27日 下午5:33:26 Administrator Exp $ 12 | */ 13 | public final class AssertUtil { 14 | 15 | public static void notBlack(String str, String assertDesc) { 16 | if (StringUtils.isBlank(str)) { 17 | throw new IllegalArgumentException(assertDesc); 18 | } 19 | } 20 | 21 | public static void notNull(Object obj, String assertDesc) { 22 | if (obj == null) { 23 | throw new IllegalArgumentException(assertDesc); 24 | } 25 | } 26 | 27 | public static void greaterThan(long value, long base, String assertDesc) { 28 | if (value <= base) { 29 | throw new IllegalArgumentException(assertDesc); 30 | } 31 | } 32 | 33 | public static void greaterThanOrEqual(long value, long base, String assertDesc) { 34 | if (value < base) { 35 | throw new IllegalArgumentException(assertDesc); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/util/ClassTool.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kuaidadi.com Inc. 3 | * Copyright (c) 2012-2016 All Rights Reserved. 4 | */ 5 | package com.didiglobal.sds.client.util; 6 | 7 | import com.didiglobal.sds.client.bean.SdsClassDefine; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | 12 | 13 | /** 14 | * 字节码解析工具类 15 | * 16 | * 参见 org.springframework.asm.ClassReader 17 | * 18 | * @author manzhizhen 19 | * @version $Id: ClassTool.java, v 0.1 2016年1月9日 下午5:34:40 Administrator Exp $ 20 | */ 21 | public class ClassTool { 22 | 23 | /** 24 | * 通过字节码获取部分类定义 25 | * 26 | * @param inputStream 27 | * @return 28 | * @throws IOException 29 | */ 30 | public static SdsClassDefine getClassDefine(InputStream inputStream) throws IOException { 31 | return SdsClassReader.getClassDefine(inputStream); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/util/DateUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.didiglobal.sds.client.util; 5 | 6 | import com.didiglobal.sds.client.contant.BizConstant; 7 | 8 | import java.text.SimpleDateFormat; 9 | import java.time.LocalDateTime; 10 | import java.time.ZoneId; 11 | import java.time.format.DateTimeFormatter; 12 | import java.util.Date; 13 | 14 | /** 15 | * @author manzhizhen 16 | * @version $Id: DateUtils.java, v 0.1 2016年2月21日 上午10:56:04 Administrator Exp $ 17 | */ 18 | public class DateUtils { 19 | 20 | public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; 21 | 22 | /** 23 | * 将日期时间转换成字符格式 24 | * 25 | * @param date 26 | * @param newFormat 27 | * @return 28 | */ 29 | public static String format(Date date, String newFormat) { 30 | if (date == null) { 31 | return null; 32 | } 33 | if (StringUtils.isBlank(newFormat)) { 34 | newFormat = DATE_TIME_FORMAT; 35 | } 36 | LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); 37 | return localDateTime.format(DateTimeFormatter.ofPattern(newFormat)); 38 | } 39 | 40 | /** 41 | * 获取当前时间处于第几个周期时间 42 | * 43 | * @param cycleTime 周期时长,单位秒 44 | * @param time UTC到现在的毫秒数 45 | * @return 当前时间处于第几个周期时间 46 | */ 47 | public static long getCycleTimeIndex(long cycleTime, long time) { 48 | return time / (cycleTime * BizConstant.MILLISECOND_IN_SECOND); 49 | } 50 | 51 | /** 52 | * 返回举例当前时间最近的上一个周期的结束时间 53 | * 54 | * @param cycleTime 周期时长,单位秒 55 | * @param time UTC到现在的毫秒数 56 | * @return 当前时间处于第几个周期时间 57 | */ 58 | public static long getLastCycleEndTime(long cycleTime, long time) { 59 | return time - (time % (cycleTime * BizConstant.MILLISECOND_IN_SECOND)); 60 | } 61 | 62 | /** 63 | * 获取指定时间秒数 64 | * 65 | * @param time UTC到现在的毫秒数 66 | * @return UTC的分钟数 67 | */ 68 | public static long getSecond(long time) { 69 | return time / BizConstant.MILLISECOND_IN_SECOND; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/util/IpUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kuaidadi.com Inc. 3 | * Copyright (c) 2012-2015 All Rights Reserved. 4 | */ 5 | package com.didiglobal.sds.client.util; 6 | 7 | import com.didiglobal.sds.client.log.SdsLoggerFactory; 8 | import org.slf4j.Logger; 9 | 10 | import java.net.Inet4Address; 11 | import java.net.InetAddress; 12 | import java.net.NetworkInterface; 13 | import java.util.Enumeration; 14 | 15 | 16 | /** 17 | * IP工具类 18 | * 19 | * @author manzhizhen 20 | * @version $Id: IpUtils.java, v 0.1 2015年9月22日 下午3:45:13 Administrator Exp $ 21 | */ 22 | public class IpUtils { 23 | 24 | private static Logger logger = SdsLoggerFactory.getDefaultLogger(); 25 | 26 | private static String ip = "Unknown"; 27 | 28 | private static String hostname = "Unknown"; 29 | 30 | static { 31 | try { 32 | 33 | Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces(); 34 | while (allNetInterfaces.hasMoreElements()) { 35 | NetworkInterface netInterface = allNetInterfaces.nextElement(); 36 | Enumeration addresses = netInterface.getInetAddresses(); 37 | while (addresses != null && addresses.hasMoreElements()) { 38 | InetAddress inetAddress = addresses.nextElement(); 39 | if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress() && inetAddress. 40 | getHostAddress() != null && inetAddress.getHostAddress().indexOf(":") == -1) { 41 | 42 | ip = inetAddress.getHostAddress(); 43 | hostname = inetAddress.getHostName(); 44 | } 45 | } 46 | } 47 | 48 | } catch (Exception e) { 49 | logger.warn("IpUtils 获取本地IP地址异常", e); 50 | } 51 | } 52 | 53 | public static String getIp() { 54 | return ip; 55 | } 56 | 57 | public static String getHostname() { 58 | return hostname; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/util/JsonUtils.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.util; 2 | 3 | /** 4 | * json相关的工具类 5 | * 6 | * @auther manzhizhen 7 | * @date 2019/5/1 8 | */ 9 | public class JsonUtils { 10 | 11 | /** 12 | * 判断该json串是否是数组类型 13 | * 14 | * @param jsonStr 15 | * @return 16 | */ 17 | public static boolean isJsonArray(String jsonStr) { 18 | 19 | if(StringUtils.isBlank(jsonStr)) { 20 | return false; 21 | } 22 | 23 | return jsonStr.trim().startsWith("["); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/util/ListUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.didiglobal.sds.client.util; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | 9 | /** 10 | * 11 | * 12 | * @author manzhizhen 13 | * @version $Id: ListUtils.java, v 0.1 2016年2月21日 上午10:46:15 Administrator Exp $ 14 | */ 15 | public class ListUtils { 16 | 17 | @SafeVarargs 18 | public static ArrayList newArrayList(E... elements) { 19 | if (elements == null) { 20 | return new ArrayList(); 21 | } 22 | 23 | ArrayList list = new ArrayList(elements.length); 24 | Collections.addAll(list, elements); 25 | 26 | return list; 27 | } 28 | 29 | public static ArrayList newArrayList() { 30 | return new ArrayList(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.didiglobal.sds.client.util; 5 | 6 | /** 7 | * 8 | * @author manzhizhen 9 | * @version $Id: StringUtils.java, v 0.1 2016年2月20日 下午9:57:10 Administrator Exp $ 10 | */ 11 | public class StringUtils { 12 | 13 | public static boolean isBlank(String value) { 14 | return value == null || "".equals(value.trim()); 15 | } 16 | 17 | public static boolean isNotBlank(String value) { 18 | return !isBlank(value); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sds-client/src/main/java/com/didiglobal/sds/client/util/TimeStatisticsUtil.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.util; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * 时间统计工具类 7 | *

8 | * Created by manzhizhen on 2016/6/21. 9 | */ 10 | public class TimeStatisticsUtil { 11 | private static ThreadLocal startTimeThreadLocal = new ThreadLocal<>(); 12 | 13 | /** 14 | * 记录开始时间 15 | */ 16 | public static void startTime() { 17 | startTime(System.nanoTime()); 18 | } 19 | 20 | /** 21 | * 记录开始时间 22 | */ 23 | public static void startTime(long time) { 24 | startTimeThreadLocal.set(time); 25 | } 26 | 27 | /** 28 | * 获取消耗的时间,单位毫秒 29 | * 注意:如果使用错误,比如没有调用startTime方法,则返回-1 30 | */ 31 | public static long getConsumeTime() { 32 | Long startTime = startTimeThreadLocal.get(); 33 | if (startTime != null) { 34 | return (System.nanoTime() - startTime) / 1000000; 35 | } 36 | 37 | return -1; 38 | } 39 | 40 | 41 | public static void main(String[] args) { 42 | 43 | long t1 = System.currentTimeMillis(); 44 | long t2 = System.nanoTime(); 45 | 46 | try { 47 | TimeUnit.SECONDS.sleep(10); 48 | } catch (InterruptedException e) { 49 | } 50 | 51 | System.out.println(System.currentTimeMillis() - t1); 52 | System.out.println(System.nanoTime() - t2); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /sds-client/src/test/java/com/didiglobal/sds/client/test/ConcurrentDowngradeTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.test; 2 | 3 | import com.didiglobal.sds.client.bean.SdsStrategy; 4 | import com.didiglobal.sds.client.counter.PowerfulCycleTimeCounter; 5 | import com.didiglobal.sds.client.service.SdsPowerfulCounterService; 6 | import com.didiglobal.sds.client.service.SdsStrategyService; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | /** 13 | * 并发量降级测试 14 | *

15 | * Created by manzhizhen on 2016/4/24. 16 | */ 17 | public class ConcurrentDowngradeTest extends AbstractDowngradeTest { 18 | 19 | private final static int CONCURRENT_THRESHOLD = 2; 20 | 21 | @Test 22 | public void test() { 23 | 24 | /** 25 | * 实际场景:5个线程,每秒访问一次业务方法,每个线程访问10次 26 | * 策略:并发阈值2,降级比例100% 27 | */ 28 | executor(); 29 | 30 | waitResult(); 31 | 32 | PowerfulCycleTimeCounter powerfulCycleTimeCounter = 33 | SdsPowerfulCounterService.getInstance().getPointCounterMap().get(getPoint()); 34 | Assert.assertNotNull(powerfulCycleTimeCounter); 35 | 36 | long lastCycleDowngradeValue = powerfulCycleTimeCounter.getLastCycleDowngradeValue(System.currentTimeMillis()); 37 | 38 | /** 39 | * 因为同时只允许两个线程来调用该方法,所以每次有3个线程会被降级,所以降级数量应该是30次 40 | */ 41 | Assert.assertEquals((getThreadNum() - CONCURRENT_THRESHOLD) * 10, lastCycleDowngradeValue); 42 | 43 | 44 | } 45 | 46 | @Override 47 | protected void initStrategy() { 48 | 49 | ConcurrentHashMap strategyMap = new ConcurrentHashMap<>(); 50 | 51 | SdsStrategy strategy = new SdsStrategy(); 52 | strategy.setPoint(getPoint()); 53 | strategy.setConcurrentThreshold(CONCURRENT_THRESHOLD); 54 | 55 | strategyMap.put(getPoint(), strategy); 56 | 57 | SdsStrategyService.getInstance().resetAll(strategyMap); 58 | } 59 | 60 | @Override 61 | protected long getExecutorTimes() { 62 | return 10; 63 | } 64 | 65 | @Override 66 | protected String getPoint() { 67 | return "concurrentPoint"; 68 | } 69 | 70 | @Override 71 | protected int getThreadNum() { 72 | return 5; 73 | } 74 | 75 | @Override 76 | protected long getTakeTime() { 77 | return 950; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /sds-client/src/test/java/com/didiglobal/sds/client/test/CustomStrategyExecutorBuilder.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.test; 2 | 3 | import com.didiglobal.sds.client.strategy.StrategyExecutorBuilder; 4 | import com.didiglobal.sds.client.strategy.executor.AbstractStrategyExecutor; 5 | 6 | /** 7 | *

description : CustomStrategyExecutorBuilder 8 | * 9 | * @author : masteryourself 10 | * @version : 1.0.1 11 | * @date : 2020/3/14 12:11 12 | */ 13 | public class CustomStrategyExecutorBuilder implements StrategyExecutorBuilder { 14 | 15 | @Override 16 | public AbstractStrategyExecutor build() { 17 | throw new UnsupportedOperationException("maybe occur error"); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /sds-client/src/test/java/com/didiglobal/sds/client/test/CustomStrategyExecutorBuilder2.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.test; 2 | 3 | import com.didiglobal.sds.client.strategy.StrategyExecutorBuilder; 4 | import com.didiglobal.sds.client.strategy.executor.*; 5 | 6 | /** 7 | *

description : CustomStrategyExecutorBuilder2 8 | * 9 | * @author : masteryourself 10 | * @version : 1.0.1 11 | * @date : 2020/3/14 12:12 12 | */ 13 | public class CustomStrategyExecutorBuilder2 implements StrategyExecutorBuilder { 14 | 15 | @Override 16 | public AbstractStrategyExecutor build() { 17 | return new VisitStrategyExecutor( 18 | new TokenBucketStrategyExecutor( 19 | new ConcurrentStrategyExecutor( 20 | new TimeoutStrategyExecutor( 21 | new ExceptionStrategyExecutor( 22 | new ExceptionRateStrategyExecutor(null) 23 | ))))); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /sds-client/src/test/java/com/didiglobal/sds/client/test/CustomStrategyExecutorBuilderTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.test; 2 | 3 | import com.didiglobal.sds.client.SdsClient; 4 | import com.didiglobal.sds.client.SdsClientFactory; 5 | import com.didiglobal.sds.client.strategy.executor.AbstractStrategyExecutor; 6 | import org.junit.Assert; 7 | import org.junit.Test; 8 | 9 | import java.lang.reflect.Field; 10 | 11 | /** 12 | *

description : CustomStrategyExecutorBuilderTest 13 | * 14 | * @author : masteryourself 15 | * @version : 1.0.1 16 | * @date : 2020/3/14 12:03 17 | */ 18 | public class CustomStrategyExecutorBuilderTest { 19 | 20 | @Test 21 | public void testInitStrategyChain() throws Exception { 22 | SdsClient client = SdsClientFactory.getOrCreateSdsClient("demo", "demo", "127.0.0.1/sds/heartbeat/pullstrategy"); 23 | Field strategyExecutorChain = client.getClass().getDeclaredField("strategyExecutorChain"); 24 | strategyExecutorChain.setAccessible(true); 25 | AbstractStrategyExecutor executor = (AbstractStrategyExecutor) strategyExecutorChain.get(client); 26 | int count = 0; 27 | while (executor != null) { 28 | executor = executor.getNext(); 29 | count++; 30 | } 31 | Assert.assertEquals(6, count); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /sds-client/src/test/java/com/didiglobal/sds/client/test/ExceptionDowngradeTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.test; 2 | 3 | 4 | import com.didiglobal.sds.client.bean.SdsStrategy; 5 | import com.didiglobal.sds.client.counter.PowerfulCycleTimeCounter; 6 | import com.didiglobal.sds.client.service.SdsPowerfulCounterService; 7 | import com.didiglobal.sds.client.service.SdsStrategyService; 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | 11 | import java.util.concurrent.ConcurrentHashMap; 12 | 13 | /** 14 | * 异常量降级测试 15 | *

16 | * Created by manzhizhen on 2016/4/24. 17 | */ 18 | public class ExceptionDowngradeTest extends AbstractDowngradeTest { 19 | 20 | private final static long EXCEPTION_THRESHOLD = 5; 21 | 22 | @Test 23 | public void test() { 24 | hasException = true; 25 | 26 | executor(); 27 | 28 | waitResult(); 29 | 30 | PowerfulCycleTimeCounter powerfulCycleTimeCounter = 31 | SdsPowerfulCounterService.getInstance().getPointCounterMap().get(getPoint()); 32 | Assert.assertNotNull(powerfulCycleTimeCounter); 33 | 34 | /** 35 | * 1个线程,共执行10次,所以业务方法会抛10个异常,我们的异常阈值是5,降级数量是10-5=5 36 | */ 37 | Assert.assertEquals(getThreadNum() * getExecutorTimes() - EXCEPTION_THRESHOLD, 38 | powerfulCycleTimeCounter.getLastCycleDowngradeValue(System.currentTimeMillis())); 39 | 40 | } 41 | 42 | @Override 43 | protected long getExecutorTimes() { 44 | return 10; 45 | } 46 | 47 | @Override 48 | protected String getPoint() { 49 | return "exceptionPoint"; 50 | } 51 | 52 | @Override 53 | protected int getThreadNum() { 54 | return 1; 55 | } 56 | 57 | @Override 58 | protected long getTakeTime() { 59 | return 950; 60 | } 61 | 62 | @Override 63 | public void initStrategy() { 64 | ConcurrentHashMap strategyMap = new ConcurrentHashMap<>(); 65 | 66 | SdsStrategy strategy = new SdsStrategy(); 67 | strategy.setPoint(getPoint()); 68 | strategy.setExceptionThreshold(EXCEPTION_THRESHOLD); 69 | 70 | strategyMap.put(getPoint(), strategy); 71 | 72 | SdsStrategyService.getInstance().resetAll(strategyMap); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /sds-client/src/test/java/com/didiglobal/sds/client/test/TokenBucketDowngradeTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.test; 2 | 3 | import com.didiglobal.sds.client.bean.SdsStrategy; 4 | import com.didiglobal.sds.client.counter.PowerfulCycleTimeCounter; 5 | import com.didiglobal.sds.client.service.SdsPowerfulCounterService; 6 | import com.didiglobal.sds.client.service.SdsStrategyService; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | /** 11 | * 令牌桶降级测试 12 | *

13 | * Created by manzhizhen on 2020/4/10. 14 | */ 15 | public class TokenBucketDowngradeTest extends AbstractDowngradeTest { 16 | 17 | private final static int TOKEN_BUCKET_GENERATED_TOKENS_IN_SECOND = 15; 18 | private final static int TOKEN_BUCKET_SIZE = 20; 19 | 20 | @Test 21 | public void test() { 22 | 23 | executor(); 24 | 25 | waitResult(); 26 | 27 | PowerfulCycleTimeCounter powerfulCycleTimeCounter = 28 | SdsPowerfulCounterService.getInstance().getPointCounterMap().get(getPoint()); 29 | Assert.assertNotNull(powerfulCycleTimeCounter); 30 | 31 | Assert.assertEquals(getExecutorTimes() * getThreadNum() - Math.max(TOKEN_BUCKET_GENERATED_TOKENS_IN_SECOND, 32 | TOKEN_BUCKET_SIZE), 33 | powerfulCycleTimeCounter.getLastCycleDowngradeValue(System.currentTimeMillis())); 34 | 35 | } 36 | 37 | @Override 38 | protected void initStrategy() { 39 | SdsStrategy strategy = new SdsStrategy(); 40 | strategy.setPoint(getPoint()); 41 | 42 | // 桶的时间长度是1秒,每秒生成15个令牌 43 | strategy.setTokenBucketGeneratedTokensInSecond(TOKEN_BUCKET_GENERATED_TOKENS_IN_SECOND); 44 | // 每个桶最多20个令牌 45 | strategy.setTokenBucketSize(TOKEN_BUCKET_SIZE); 46 | 47 | SdsStrategyService.getInstance().resetOne(getPoint(), strategy); 48 | } 49 | 50 | @Override 51 | protected long getExecutorTimes() { 52 | return 100; 53 | } 54 | 55 | @Override 56 | protected String getPoint() { 57 | return "tokenBucketPoint"; 58 | } 59 | 60 | @Override 61 | protected int getThreadNum() { 62 | return 1; 63 | } 64 | 65 | @Override 66 | protected long getTakeTime() { 67 | return 1; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /sds-client/src/test/java/com/didiglobal/sds/client/test/VisitDowngradeTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.client.test; 2 | 3 | import com.didiglobal.sds.client.bean.SdsStrategy; 4 | import com.didiglobal.sds.client.counter.PowerfulCycleTimeCounter; 5 | import com.didiglobal.sds.client.service.SdsPowerfulCounterService; 6 | import com.didiglobal.sds.client.service.SdsStrategyService; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | /** 13 | * 访问量降级测试 14 | *

15 | * Created by manzhizhen on 2016/4/24. 16 | */ 17 | public class VisitDowngradeTest extends AbstractDowngradeTest { 18 | 19 | private final static long VISITT_HRESHOLD = 5L; 20 | 21 | @Test 22 | public void test() { 23 | 24 | executor(); 25 | 26 | waitResult(); 27 | 28 | PowerfulCycleTimeCounter powerfulCycleTimeCounter = 29 | SdsPowerfulCounterService.getInstance().getPointCounterMap().get(getPoint()); 30 | Assert.assertNotNull(powerfulCycleTimeCounter); 31 | 32 | Assert.assertEquals(getExecutorTimes() * getThreadNum() - VISITT_HRESHOLD, 33 | powerfulCycleTimeCounter.getLastCycleDowngradeValue(System.currentTimeMillis())); 34 | 35 | } 36 | 37 | @Override 38 | protected void initStrategy() { 39 | ConcurrentHashMap strategyMap = new ConcurrentHashMap<>(); 40 | 41 | SdsStrategy strategy = new SdsStrategy(); 42 | strategy.setPoint(getPoint()); 43 | 44 | strategy.setVisitThreshold(VISITT_HRESHOLD); 45 | 46 | strategyMap.put(getPoint(), strategy); 47 | 48 | SdsStrategyService.getInstance().resetAll(strategyMap); 49 | } 50 | 51 | @Override 52 | protected long getExecutorTimes() { 53 | return 10; 54 | } 55 | 56 | @Override 57 | protected String getPoint() { 58 | return "visitPoint"; 59 | } 60 | 61 | @Override 62 | protected int getThreadNum() { 63 | return 1; 64 | } 65 | 66 | @Override 67 | protected long getTakeTime() { 68 | return 950; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /sds-client/src/test/resources/META-INF/services/com.didiglobal.sds.client.strategy.StrategyExecutorBuilder: -------------------------------------------------------------------------------- 1 | com.didiglobal.sds.client.test.CustomStrategyExecutorBuilder2 2 | com.didiglobal.sds.client.test.CustomStrategyExecutorBuilder 3 | -------------------------------------------------------------------------------- /sds-client/src/test/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /sds-easy/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | com.didiglobal.sds 8 | sds-base 9 | ${revision} 10 | ../pom.xml 11 | 12 | 13 | 4.0.0 14 | 15 | com.didiglobal.sds 16 | sds-easy 17 | 18 | sds-easy 19 | 20 | https://github.com/didi/sds 21 | 22 | 23 | 24 | com.didiglobal.sds 25 | sds-client 26 | 27 | 28 | 29 | 30 | org.slf4j 31 | slf4j-log4j12 32 | test 33 | 34 | 35 | junit 36 | junit 37 | test 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /sds-easy/src/main/java/com/didiglobal/sds/easy/BizFunction.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.easy; 2 | 3 | /** 4 | * 业务方法 5 | * 注意:Sds内置的函数接口,类等于JDK8的Supplier,为了支持JDK8之前的版本,所以定制了该接口 6 | * 7 | * @param 8 | */ 9 | @FunctionalInterface 10 | public interface BizFunction { 11 | 12 | /** 13 | * 执行业务逻辑并返回结果 14 | * 15 | * @return 16 | */ 17 | T invokeBizMethod(); 18 | } 19 | -------------------------------------------------------------------------------- /sds-easy/src/main/java/com/didiglobal/sds/easy/BizFunctionWithoutReturn.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.easy; 2 | 3 | /** 4 | * @author manzhizhen 5 | * @date 2019-07-18 6 | */ 7 | public interface BizFunctionWithoutReturn { 8 | 9 | /** 10 | * 执行业务逻辑 11 | */ 12 | void invokeBizMethod(); 13 | } 14 | -------------------------------------------------------------------------------- /sds-easy/src/main/java/com/didiglobal/sds/easy/DowngradeFunction.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.easy; 2 | 3 | /** 4 | * 降级后执行的方法 5 | * Sds内置的函数接口,类等于JDK8的Supplier,为了支持JDK8之前的版本,所以定制了该接口 6 | * 7 | * @param 8 | */ 9 | @FunctionalInterface 10 | public interface DowngradeFunction { 11 | 12 | /** 13 | * 执行业务逻辑并返回结果 14 | * 15 | * @return 16 | */ 17 | T invokeDowngradeMethod(); 18 | } 19 | -------------------------------------------------------------------------------- /sds-easy/src/main/java/com/didiglobal/sds/easy/DowngradeFunctionWithoutReturn.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.easy; 2 | 3 | /** 4 | * 降级后执行的无返回值的方法 5 | * Sds内置的函数接口,类等于JDK8的Supplier,为了支持JDK8之前的版本,所以定制了该接口 6 | */ 7 | @FunctionalInterface 8 | public interface DowngradeFunctionWithoutReturn { 9 | 10 | /** 11 | * 执行降级逻辑 12 | * 13 | */ 14 | void invokeDowngradeMethod(); 15 | } 16 | -------------------------------------------------------------------------------- /sds-easy/src/test/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /sds-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | com.didiglobal.sds 7 | sds-base 8 | ${revision} 9 | ../pom.xml 10 | 11 | 12 | 4.0.0 13 | 14 | com.didiglobal.sds 15 | sds-example 16 | 17 | pom 18 | 19 | sds-example 20 | 21 | https://github.com/didi/sds 22 | 23 | 24 | UTF-8 25 | 1.7 26 | 1.7 27 | 28 | 29 | 30 | sds-apache-dubbo-example 31 | sds-client-example 32 | 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-test 38 | test 39 | 40 | 41 | org.junit.vintage 42 | junit-vintage-engine 43 | 44 | 45 | 46 | 47 | junit 48 | junit 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.apache.maven.plugins 56 | maven-deploy-plugin 57 | 58 | true 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /sds-example/sds-apache-dubbo-example/README.md: -------------------------------------------------------------------------------- 1 | ## dubbo-2.7.3 2 | * start provider 3 | ``` 4 | mvn clean package -Dmaven.test.skip=true -Pdubbo-2.7.3 5 | java -jar target/sds-apache-dubbo-example-1.0.0-SNAPSHOT.jar 6 | ``` 7 | 8 | *run test 9 | ``` 10 | mvn package -Pdubbo-2.7.3 11 | ``` 12 | 13 | ## dubbo-2.7.5 14 | * start provider 15 | ``` 16 | mvn clean package -Dmaven.test.skip=true -Pdubbo-2.7.5 17 | java -jar target/sds-apache-dubbo-example-1.0.0-SNAPSHOT.jar 18 | ``` 19 | 20 | *run test 21 | ``` 22 | mvn package -Pdubbo-2.7.5 23 | ``` 24 | 25 | ## dubbo-2.7.6 26 | * start provider 27 | ``` 28 | mvn clean package -Dmaven.test.skip=true -Pdubbo-2.7.6 29 | java -jar target/sds-apache-dubbo-example-1.0.0-SNAPSHOT.jar 30 | ``` 31 | 32 | *run test 33 | ``` 34 | mvn package -Pdubbo-2.7.6 35 | ``` 36 | -------------------------------------------------------------------------------- /sds-example/sds-apache-dubbo-example/src/main/java/com/didiglobal/sds/example/DemoServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example; 2 | 3 | import com.didiglobal.sds.client.config.SdsDowngradeActionNotify; 4 | import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | 10 | import java.io.IOException; 11 | 12 | 13 | @SpringBootApplication 14 | @EnableDubbo 15 | public class DemoServiceApplication { 16 | 17 | private static final Logger logger = LoggerFactory.getLogger(DemoServiceApplication.class); 18 | 19 | static { 20 | SdsDowngradeActionNotify.addDowngradeActionListener((point, downgradeActionType, date) -> { 21 | logger.info("point:{} is downgraded at {} type:{}", point, date, downgradeActionType); 22 | }); 23 | 24 | } 25 | 26 | public static void main(String[] args) throws IOException { 27 | SpringApplication.run(DemoServiceApplication.class, args); 28 | System.in.read(); // 按任意键退出 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /sds-example/sds-apache-dubbo-example/src/main/java/com/didiglobal/sds/example/api/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example.api; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | /** 6 | * Created by sea on 2020-03-28. 7 | */ 8 | public interface HelloService { 9 | 10 | String hello(String content); 11 | 12 | CompletableFuture asyncHello(String content); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /sds-example/sds-apache-dubbo-example/src/main/java/com/didiglobal/sds/example/service/HelloServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example.service; 2 | 3 | import com.didiglobal.sds.example.api.HelloService; 4 | import org.apache.dubbo.config.annotation.Service; 5 | import org.springframework.context.annotation.Profile; 6 | 7 | import java.util.concurrent.CompletableFuture; 8 | import java.util.concurrent.ThreadLocalRandom; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | /** 12 | * Created by sea on 2020-03-28. 13 | */ 14 | @Service(interfaceClass = HelloService.class) 15 | @Profile("provider") 16 | public class HelloServiceImpl implements HelloService { 17 | 18 | @Override 19 | public String hello(String content) { 20 | try { 21 | TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(1,10)); 22 | } catch (InterruptedException e) { 23 | e.printStackTrace(); 24 | } 25 | return "world"; 26 | } 27 | 28 | @Override 29 | public CompletableFuture asyncHello(String content) { 30 | return CompletableFuture.supplyAsync(() -> { 31 | try { 32 | TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(1,10)); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } 36 | return "world"; 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sds-example/sds-apache-dubbo-example/src/main/resources/application-consumer.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: hello-consumer 4 | main: 5 | allow-bean-definition-overriding: true 6 | dubbo: 7 | application: 8 | name: hello-consumer 9 | registry: 10 | address: N/A 11 | sds: 12 | appGroupName: demo 13 | appName: demo-dubbo-consumer 14 | serverAddrList: https://sds.chpengzh.com 15 | -------------------------------------------------------------------------------- /sds-example/sds-apache-dubbo-example/src/main/resources/application-provider.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: hello-provider 4 | main: 5 | allow-bean-definition-overriding: true 6 | dubbo: 7 | application: 8 | name: hello-provider 9 | protocol: 10 | name: dubbo 11 | port: 12345 12 | registry: 13 | address: N/A 14 | sds: 15 | appGroupName: demo 16 | appName: demo-dubbo-provider 17 | serverAddrList: https://sds.chpengzh.com 18 | -------------------------------------------------------------------------------- /sds-example/sds-apache-dubbo-example/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | active: provider 4 | -------------------------------------------------------------------------------- /sds-example/sds-apache-dubbo-example/src/test/java/com/didiglobal/sds/example/DemoServiceConsumerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example; 2 | 3 | import com.didiglobal.sds.example.api.HelloService; 4 | import org.apache.dubbo.config.annotation.Reference; 5 | import org.junit.Test; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | import org.springframework.test.context.ActiveProfiles; 8 | 9 | import java.util.concurrent.CompletableFuture; 10 | import java.util.concurrent.TimeUnit; 11 | import java.util.stream.IntStream; 12 | 13 | @SpringBootTest 14 | @ActiveProfiles("consumer") 15 | class DemoServiceConsumerApplicationTests { 16 | 17 | @Reference(timeout = 3000, url = "127.0.0.1:12345") 18 | HelloService helloService; 19 | 20 | 21 | @Test 22 | void testHello() { 23 | IntStream.rangeClosed(1, 100) 24 | .forEach(i -> { 25 | try { 26 | System.out.println(helloService.hello("abc")); 27 | TimeUnit.SECONDS.sleep(1); 28 | } catch (Exception e) { 29 | e.printStackTrace(); 30 | } 31 | }); 32 | } 33 | 34 | @Test 35 | public void testHelloAsync() { 36 | IntStream.rangeClosed(1, 100) 37 | .forEach(i -> { 38 | try { 39 | CompletableFuture future = helloService.asyncHello("abc"); 40 | System.out.println(future.get()); 41 | TimeUnit.SECONDS.sleep(1); 42 | } catch (Exception e) { 43 | e.printStackTrace(); 44 | } 45 | }); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /sds-example/sds-client-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | com.didiglobal.sds 7 | sds-example 8 | ${revision} 9 | ../pom.xml 10 | 11 | 12 | 4.0.0 13 | 14 | com.didiglobal.sds 15 | sds-client-example 16 | 17 | sds-client-example 18 | 19 | https://github.com/didi/sds 20 | 21 | 22 | UTF-8 23 | 1.7 24 | 1.7 25 | 26 | 27 | 28 | 29 | com.didiglobal.sds 30 | sds-easy 31 | 32 | 33 | com.didiglobal.sds 34 | sds-aspectj 35 | 36 | 37 | com.didiglobal.sds 38 | sds-spring-boot-starter 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-test 43 | 44 | 45 | 46 | org.springframework 47 | spring-aop 48 | 49 | 50 | org.springframework 51 | spring-beans 52 | 53 | 54 | org.springframework 55 | spring-core 56 | 57 | 58 | org.springframework 59 | spring-context 60 | 61 | 62 | org.springframework 63 | spring-context-support 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /sds-example/sds-client-example/src/main/java/com/didiglobal/sds/example/chapter1/UseOriginApiAndSdsAdmin.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example.chapter1; 2 | 3 | import com.didiglobal.sds.client.SdsClient; 4 | import com.didiglobal.sds.client.SdsClientFactory; 5 | 6 | import java.util.concurrent.ThreadLocalRandom; 7 | 8 | /** 9 | * 【演示】通过原生API来使用SDS,结合sds-admin来配置降级策略 10 | * 11 | * @Author: manzhizhen 12 | * @Date: Create in 2020-03-22 12:26 13 | */ 14 | public class UseOriginApiAndSdsAdmin { 15 | 16 | // 这里配置我们官方的远程演示sds-admin地址 17 | private static final String SERVER_URL = "https://sds.chpengzh.com/"; 18 | 19 | // 保证SdsClient对象的单例使用(线程安全) 20 | private static SdsClient sdsClient = SdsClientFactory.getOrCreateSdsClient("BikeBusinessDepartment", "order", SERVER_URL); 21 | 22 | // 创建订单的降级点名称 23 | private static final String CREATE_ORDER_POINT = "createOrderPoint"; 24 | 25 | public static void main(String[] args) { 26 | 27 | /** 28 | * 模拟业务方法的调用者,调用2000次 29 | * 注意:我们已经在演示sds-admin中配置了降级点createOrderPoint的降级策略,此时该业务方法的执行受到SDS的保护,在10s的滑动窗口中,最多调用1000次 30 | */ 31 | int times = 2000; 32 | while(times-- > 0) { 33 | Long orderId = createOrder(12345L, "杭州西湖区西溪谷G座"); 34 | System.out.println("新创建的订单id:" + orderId); 35 | } 36 | } 37 | 38 | /** 39 | * 经过SDS包装的某个业务方法:创建订单 40 | * 41 | * @param userId 42 | * @param address 43 | * @return 创建的订单ID 44 | */ 45 | public static Long createOrder(Long userId, String address) { 46 | try { 47 | 48 | // 1. 降级判断:如果需要降级,那我们根据业务逻辑来默认返回null(当然也可以选择抛我们自己定义的业务异常) 49 | if (sdsClient.shouldDowngrade(CREATE_ORDER_POINT)) { 50 | return null; 51 | } 52 | 53 | // 2. 这里是正常的业务逻辑:用控制台输出来代表业务逻辑,为简单起见,返回的订单ID随机生成 54 | System.out.println("您的业务方法已经执行,userId:" + userId + ", address:" + address); 55 | return ThreadLocalRandom.current().nextLong(0, 10000000); 56 | 57 | } catch (Exception e) { 58 | 59 | // 3. 这里用于统计异常量 60 | sdsClient.exceptionSign(CREATE_ORDER_POINT, e); 61 | // 记得捕获完还得抛出去 62 | throw e; 63 | 64 | } finally { 65 | // 4. 回收资源,一般在finally代码中调用 66 | sdsClient.downgradeFinally(CREATE_ORDER_POINT); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /sds-example/sds-client-example/src/main/java/com/didiglobal/sds/example/chapter2/UserSdsEasyAndSdsAdmin.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example.chapter2; 2 | 3 | import com.didiglobal.sds.client.SdsClient; 4 | import com.didiglobal.sds.client.SdsClientFactory; 5 | import com.didiglobal.sds.easy.SdsEasyUtil; 6 | 7 | import java.util.concurrent.ThreadLocalRandom; 8 | 9 | /** 10 | * 【演示】使用sds-easy中提供的Lamdba表达式的方式来使用sds-client 11 | * 12 | * @Author: manzhizhen 13 | * @Date: Create in 2020-03-27 09:04 14 | */ 15 | public class UserSdsEasyAndSdsAdmin { 16 | 17 | // 这里配置我们官方的远程演示sds-admin地址 18 | private static final String SERVER_URL = "https://sds.chpengzh.com/"; 19 | 20 | // 保证SdsClient对象的单例使用(线程安全) 21 | private static SdsClient sdsClient = SdsClientFactory.getOrCreateSdsClient("BikeBusinessDepartment", "order", 22 | SERVER_URL); 23 | 24 | // 创建订单的降级点名称 25 | private static final String CREATE_ORDER_POINT = "createOrderPoint"; 26 | 27 | public static void main(String[] args) { 28 | 29 | /** 30 | * 模拟业务方法的调用者,调用2000次 31 | * 注意:我们已经在演示sds-admin中配置了降级点createOrderPoint的降级策略,此时该业务方法的执行受到SDS的保护,在10s的滑动窗口中,最多调用1000次 32 | */ 33 | int times = 2000; 34 | while (times-- > 0) { 35 | 36 | /** 37 | * 使用了sds-easy的 {@link SdsEasyUtil} 后,再也不用在业务方法中进行SDS的埋点了,多方便啊!!! 38 | * 注意:我们这里设置了降级后默认的返回值是null 39 | */ 40 | Long orderId = SdsEasyUtil.invokerMethod(CREATE_ORDER_POINT, null, 41 | () -> createOrder(12345L, "杭州西湖区西溪谷G座") 42 | ); 43 | 44 | System.out.println("新创建的订单id:" + orderId); 45 | } 46 | 47 | } 48 | 49 | /** 50 | * 某个业务方法:创建订单 51 | * 52 | * 注意:因为我们打算使用{@link SdsEasyUtil},所以这里业务方法不需要进行sds-client的埋点 53 | * 54 | * @param userId 55 | * @param address 56 | * @return 创建的订单ID 57 | */ 58 | public static Long createOrder(Long userId, String address) { 59 | 60 | // 1. 这里是正常的业务逻辑:用控制台输出来代表业务逻辑,为简单起见,返回的订单ID随机生成 61 | System.out.println("您的业务方法已经执行,userId:" + userId + ", address:" + address); 62 | return ThreadLocalRandom.current().nextLong(0, 10000000); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /sds-example/sds-client-example/src/main/java/com/didiglobal/sds/example/chapter3/UseAnnotationByAspectj.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example.chapter3; 2 | 3 | import com.didiglobal.sds.client.exception.SdsException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.support.ClassPathXmlApplicationContext; 6 | 7 | /** 8 | * 【演示】通过Spring AOP(Aspectj) + 注解 的方式来使用SDS 9 | * 10 | * @Author: manzhizhen 11 | * @Date: Create in 2020-03-22 21:31 12 | */ 13 | public class UseAnnotationByAspectj { 14 | 15 | public static void main(String[] args) { 16 | // create and configure beans 17 | ApplicationContext context = new ClassPathXmlApplicationContext("chapter3-spring.xml"); 18 | OrderManageService orderManageService = (OrderManageService) context.getBean( 19 | "orderManageService"); 20 | 21 | /** 22 | * 模拟业务方法的调用者,调用2000次 23 | * 24 | * 注意:我们已经在演示sds-admin中配置了降级点createOrderPoint的降级策略,此时该业务方法的执行受到SDS的包括,在10s的滑动窗口中,最多调用1000次 25 | */ 26 | int times = 2000; 27 | while (times-- > 0) { 28 | 29 | Long orderId = null; 30 | try { 31 | orderId = orderManageService.createOrder(12345L, "杭州西湖区西溪谷G座"); 32 | System.out.println("新创建的订单id:" + orderId); 33 | 34 | } catch (SdsException e) { 35 | System.out.println("此次调用已经被降级!"); 36 | } 37 | 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /sds-example/sds-client-example/src/main/java/com/didiglobal/sds/example/chapter4/OrderManageService.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example.chapter4; 2 | 3 | import com.didiglobal.sds.client.SdsClient; 4 | import com.didiglobal.sds.client.annotation.SdsDowngradeMethod; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.concurrent.ThreadLocalRandom; 9 | 10 | /** 11 | * 模拟业务实现类 12 | * 13 | * 这里演示两种方式使用SDS,方式1:Spring AOP + 注解 的方式; 方式2:使用 SdsEasyUtil 或 SdsClient 14 | * 15 | * @Author: manzhizhen 16 | * @Date: Create in 2020-03-22 22:39 17 | */ 18 | @Service("orderManageService") 19 | public class OrderManageService { 20 | 21 | // 创建订单的降级点名称 22 | public final static String CREATE_ORDER_POINT = "createOrderPoint"; 23 | public final static String CREATE_ORDER_POINT_1 = "createOrderPoint1"; 24 | 25 | // 如果直接使用SDS API,那么可以使用Spring来注入SdsClient 26 | @Autowired 27 | private SdsClient sdsClient; 28 | 29 | /** 30 | * 方式1:Spring AOP + 注解 的方式 31 | * 32 | * 创建订单 33 | * 34 | * 注意:使用 {@link SdsDowngradeMethod} 默认降级后的行为是抛 {@link com.didiglobal.sds.client.exception.SdsException} 异常 35 | * 36 | * @param userId 37 | * @param address 38 | * @return 创建的订单ID 39 | */ 40 | @SdsDowngradeMethod(point = CREATE_ORDER_POINT) 41 | public Long createOrder(Long userId, String address) { 42 | 43 | // 1. 这里是正常的业务逻辑:用控制台输出来代表业务逻辑,为简单起见,返回的订单ID随机生成 44 | System.out.println("您的业务方法已经执行,userId:" + userId + ", address:" + address); 45 | return ThreadLocalRandom.current().nextLong(0, 10000000); 46 | } 47 | 48 | /** 49 | * 方式2:a-在调用方使用{@link com.didiglobal.sds.easy.SdsEasyUtil}来调用该方法 或者 50 | * b-直接使用sdsClient来包createOrder1, 51 | * 这里就不在演示了,参见{@link com.didiglobal.sds.example.chapter1.UseOriginApi#createOrder(Long, String)}) 52 | * 53 | * 创建订单1 54 | * 55 | * @param userId 56 | * @param address 57 | * @return 创建的订单ID 58 | */ 59 | public Long createOrder1(Long userId, String address) { 60 | 61 | // 1. 这里是正常的业务逻辑:用控制台输出来代表业务逻辑,为简单起见,返回的订单ID随机生成 62 | System.out.println("您的业务方法已经执行,userId:" + userId + ", address:" + address); 63 | return ThreadLocalRandom.current().nextLong(0, 10000000); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sds-example/sds-client-example/src/main/java/com/didiglobal/sds/example/chapter4/SdsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example.chapter4; 2 | 3 | import com.didiglobal.sds.aspectj.SdsPointAspect; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * @Author: manzhizhen 9 | * @Date: Create in 2020-03-29 20:27 10 | */ 11 | @Configuration 12 | public class SdsConfiguration { 13 | @Bean 14 | public SdsPointAspect createSdsPointAspect() { 15 | return new SdsPointAspect(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sds-example/sds-client-example/src/main/java/com/didiglobal/sds/example/chapter4/SpringBoootWithSds.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example.chapter4; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * Spring Boot启动类 8 | * 9 | * @Author: manzhizhen 10 | * @Date: Create in 2020-03-29 14:31 11 | */ 12 | @SpringBootApplication 13 | public class SpringBoootWithSds { 14 | 15 | public static void main(String[] args) { 16 | try { 17 | SpringApplication.run(SpringBoootWithSds.class, args); 18 | } catch (Exception e) { 19 | e.printStackTrace(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /sds-example/sds-client-example/src/main/java/com/didiglobal/sds/example/chapter4/SpringBoootWithSdsTest.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.example.chapter4; 2 | 3 | import com.didiglobal.sds.client.exception.SdsException; 4 | import com.didiglobal.sds.easy.SdsEasyUtil; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | /** 11 | * 【演示】Sds和Spring Boot打通 12 | * 13 | * 运行Spring Boot的单元测试来验证结果 14 | * 15 | * @Author: manzhizhen 16 | * @Date: Create in 2020-03-29 18:34 17 | */ 18 | @RunWith(SpringRunner.class) 19 | @SpringBootTest 20 | public class SpringBoootWithSdsTest { 21 | 22 | @Autowired 23 | private OrderManageService orderManageService; 24 | 25 | @org.junit.Test 26 | public void test() { 27 | int times = 2000; 28 | while (times-- > 0) { 29 | Long orderId = null; 30 | try { 31 | orderId = orderManageService.createOrder(12345L, "杭州西湖区西溪谷G座"); 32 | System.out.println("createOrder新创建的订单id:" + orderId); 33 | 34 | } catch (SdsException e) { 35 | System.out.println("createOrder此次调用已经被降级!"); 36 | } 37 | } 38 | 39 | 40 | times = 2000; 41 | while (times-- > 0) { 42 | Long orderId = null; 43 | try { 44 | 45 | orderId = SdsEasyUtil.invokerMethod(OrderManageService.CREATE_ORDER_POINT_1, null, 46 | ()-> orderManageService.createOrder1(12345L, "杭州西湖区西溪谷G座")); 47 | 48 | System.out.println("createOrder1新创建的订单id:" + orderId); 49 | 50 | } catch (SdsException e) { 51 | System.out.println("createOrder1此次调用已经被降级!"); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /sds-example/sds-client-example/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | sds.app-group-name=BikeBusinessDepartment 2 | sds.app-name=order 3 | sds.server-addr-list=https://sds.chpengzh.com/ 4 | 5 | spring.main.web-application-type=none -------------------------------------------------------------------------------- /sds-example/sds-client-example/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.profiles.active=dev -------------------------------------------------------------------------------- /sds-example/sds-client-example/src/main/resources/chapter3-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /sds-extension/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.didiglobal.sds 7 | sds-base 8 | ${revision} 9 | ../pom.xml 10 | 11 | 12 | 4.0.0 13 | 14 | com.didiglobal.sds 15 | sds-extension 16 | 17 | pom 18 | 19 | 20 | sds-dubbo 21 | sds-apache-dubbo 22 | sds-okhttp 23 | sds-spring-boot 24 | sds-aspectj 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /sds-extension/sds-apache-dubbo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | com.didiglobal.sds 8 | sds-extension 9 | ${revision} 10 | ../pom.xml 11 | 12 | 13 | com.didiglobal.sds 14 | sds-apache-dubbo 15 | 16 | 4.0.0 17 | 18 | https://github.com/didi/sds 19 | 20 | 21 | 2.7.5 22 | 23 | 24 | 25 | 26 | com.didiglobal.sds 27 | sds-client 28 | 29 | 30 | 31 | org.apache.dubbo 32 | dubbo 33 | provided 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /sds-extension/sds-apache-dubbo/src/main/resources/META-INF/dubbo/org.apache.dubbo.rpc.Filter: -------------------------------------------------------------------------------- 1 | SdsApacheDubboFilter=com.didiglobal.sds.extension.dubbo.filter.SdsApacheDubboFilter 2 | 3 | 4 | -------------------------------------------------------------------------------- /sds-extension/sds-aspectj/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | com.didiglobal.sds 5 | sds-extension 6 | ${revision} 7 | ../pom.xml 8 | 9 | 10 | 4.0.0 11 | 12 | com.didiglobal.sds 13 | sds-aspectj 14 | 15 | jar 16 | sds-aspectj 17 | 18 | https://github.com/didi/sds 19 | 20 | 21 | 22 | com.didiglobal.sds 23 | sds-client 24 | 25 | 26 | 27 | org.aspectj 28 | aspectjrt 29 | 30 | 31 | org.aspectj 32 | aspectjweaver 33 | 34 | 35 | 36 | junit 37 | junit 38 | test 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /sds-extension/sds-dubbo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | com.didiglobal.sds 8 | sds-extension 9 | ${revision} 10 | ../pom.xml 11 | 12 | 13 | com.didiglobal.sds 14 | sds-dubbo 15 | 16 | jar 17 | 18 | 4.0.0 19 | 20 | https://github.com/didi/sds 21 | 22 | 23 | 2.6.5 24 | 25 | 26 | 27 | 28 | com.didiglobal.sds 29 | sds-client 30 | 31 | 32 | 33 | com.alibaba 34 | dubbo 35 | ${dubbo.version} 36 | provided 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /sds-extension/sds-dubbo/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter: -------------------------------------------------------------------------------- 1 | SdsDubboFilter=com.didiglobal.sds.extension.dubbo.filter.SdsDubboFilter 2 | 3 | 4 | -------------------------------------------------------------------------------- /sds-extension/sds-okhttp/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.didiglobal.sds 8 | sds-extension 9 | ${revision} 10 | ../pom.xml 11 | 12 | 13 | com.didiglobal.sds 14 | sds-okhttp 15 | 16 | https://github.com/didi/sds 17 | 18 | 19 | 20 | com.squareup.okhttp3 21 | okhttp 22 | 23 | 24 | 25 | com.didiglobal.sds 26 | sds-client 27 | 28 | 29 | 30 | org.apache.commons 31 | commons-lang3 32 | 33 | 34 | commons-collections 35 | commons-collections 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /sds-extension/sds-okhttp/src/main/java/com/didiglobal/sds/extension/okhttp/SdsOkHttpInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.extension.okhttp; 2 | 3 | import com.didiglobal.sds.client.SdsClient; 4 | import com.didiglobal.sds.client.SdsClientFactory; 5 | import com.didiglobal.sds.client.contant.ExceptionCode; 6 | import com.didiglobal.sds.client.exception.SdsException; 7 | import okhttp3.Interceptor; 8 | import okhttp3.Request; 9 | import okhttp3.Response; 10 | import org.apache.commons.lang3.StringUtils; 11 | 12 | import java.io.IOException; 13 | 14 | /** 15 | * Created by tianyulei on 2019/8/11 16 | **/ 17 | public class SdsOkHttpInterceptor implements Interceptor { 18 | @Override 19 | public Response intercept(Chain chain) throws IOException { 20 | Request request = chain.request(); 21 | String url = request.url().toString(); 22 | if(StringUtils.isEmpty(url)){ 23 | return chain.proceed(request); 24 | } 25 | SdsClient sdsClient = SdsClientFactory.getSdsClient(); 26 | String point = url + "-OkHttpPoint"; 27 | 28 | if(sdsClient.shouldDowngrade(point)){ 29 | throw new SdsException(point, ExceptionCode.DOWNGRADE.getCode(), "okhttp request has degraded"); 30 | } 31 | Throwable exception = null; 32 | try{ 33 | Response response = chain.proceed(request); 34 | return response; 35 | }catch (Throwable e){ 36 | exception = e; 37 | throw e; 38 | } finally { 39 | if(exception != null){ 40 | sdsClient.exceptionSign(point, exception); 41 | sdsClient.downgradeFinally(point); 42 | } 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sds-extension/sds-spring-boot/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.didiglobal.sds 7 | sds-extension 8 | ${revision} 9 | ../pom.xml 10 | 11 | 4.0.0 12 | 13 | com.didiglobal.sds 14 | sds-spring-boot 15 | 16 | pom 17 | 18 | 19 | sds-spring-boot-autoconfigure 20 | sds-spring-boot-starter 21 | 22 | 23 | -------------------------------------------------------------------------------- /sds-extension/sds-spring-boot/sds-spring-boot-autoconfigure/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | com.didiglobal.sds 7 | sds-spring-boot 8 | ${revision} 9 | ../pom.xml 10 | 11 | 4.0.0 12 | 13 | com.didiglobal.sds 14 | sds-spring-boot-autoconfigure 15 | jar 16 | 17 | sds-spring-boot-autoconfigure 18 | 19 | https://github.com/didi/sds 20 | 21 | 22 | UTF-8 23 | 1.7 24 | 1.7 25 | 26 | 27 | 28 | 29 | 30 | com.didiglobal.sds 31 | sds-client 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-autoconfigure 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-logging 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-test 46 | test 47 | 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-configuration-processor 52 | true 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /sds-extension/sds-spring-boot/sds-spring-boot-autoconfigure/src/main/java/com/didiglobal/sds/extension/spring/boot/autoconfigure/SdsAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.extension.spring.boot.autoconfigure; 2 | 3 | 4 | import com.didiglobal.sds.client.SdsClient; 5 | import com.didiglobal.sds.client.SdsClientFactory; 6 | import com.didiglobal.sds.client.log.SdsLoggerFactory; 7 | import org.slf4j.Logger; 8 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 9 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | 14 | /** 15 | * 将SDS和Spring Boot的自动配置打通 16 | */ 17 | @Configuration 18 | @EnableConfigurationProperties({SdsProperties.class}) 19 | public class SdsAutoConfiguration { 20 | 21 | private Logger logger = SdsLoggerFactory.getDefaultLogger(); 22 | 23 | @Bean 24 | @ConditionalOnMissingBean 25 | public SdsClient sdsClient(SdsProperties sdsProperties) { 26 | SdsClient sdsClient = SdsClientFactory.getOrCreateSdsClient(sdsProperties.getAppGroupName(), sdsProperties.getAppName(), 27 | sdsProperties.getServerAddrList()); 28 | logger.info("SdsAutoConfiguration create SdsClient with sdsProperties:{}", sdsProperties); 29 | return sdsClient; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sds-extension/sds-spring-boot/sds-spring-boot-autoconfigure/src/main/java/com/didiglobal/sds/extension/spring/boot/autoconfigure/SdsProperties.java: -------------------------------------------------------------------------------- 1 | package com.didiglobal.sds.extension.spring.boot.autoconfigure; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | /** 6 | * 对应properties文件的: 7 | * sds.app.group.name, sds.app.name, sds.server.addr.list 8 | */ 9 | @ConfigurationProperties("sds") 10 | public class SdsProperties { 11 | 12 | private String appGroupName; 13 | 14 | private String appName; 15 | 16 | private String serverAddrList; 17 | 18 | public String getAppGroupName() { 19 | return appGroupName; 20 | } 21 | 22 | public void setAppGroupName(String appGroupName) { 23 | this.appGroupName = appGroupName; 24 | } 25 | 26 | public String getAppName() { 27 | return appName; 28 | } 29 | 30 | public void setAppName(String appName) { 31 | this.appName = appName; 32 | } 33 | 34 | public String getServerAddrList() { 35 | return serverAddrList; 36 | } 37 | 38 | public void setServerAddrList(String serverAddrList) { 39 | this.serverAddrList = serverAddrList; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /sds-extension/sds-spring-boot/sds-spring-boot-autoconfigure/src/main/resources/META-INF/spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": [ 3 | { 4 | "name": "sds", 5 | "type": "com.didiglobal.sds.extension.spring.boot.autoconfigure.SdsProperties", 6 | "sourceType": "com.didiglobal.sds.extension.spring.boot.autoconfigure.SdsProperties" 7 | } 8 | ], 9 | "properties": [ 10 | { 11 | "name": "sds.app-group-name", 12 | "type": "java.lang.String", 13 | "sourceType": "com.didiglobal.sds.extension.spring.boot.autoconfigure.SdsProperties" 14 | }, 15 | { 16 | "name": "sds.app-name", 17 | "type": "java.lang.String", 18 | "sourceType": "com.didiglobal.sds.extension.spring.boot.autoconfigure.SdsProperties" 19 | }, 20 | { 21 | "name": "sds.server-addr-list", 22 | "type": "java.lang.String", 23 | "sourceType": "com.didiglobal.sds.extension.spring.boot.autoconfigure.SdsProperties" 24 | } 25 | ], 26 | "hints": [] 27 | } -------------------------------------------------------------------------------- /sds-extension/sds-spring-boot/sds-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # Auto Configure 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 3 | com.didiglobal.sds.extension.spring.boot.autoconfigure.SdsAutoConfiguration 4 | -------------------------------------------------------------------------------- /sds-extension/sds-spring-boot/sds-spring-boot-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.didiglobal.sds 7 | sds-spring-boot 8 | ${revision} 9 | ../pom.xml 10 | 11 | 4.0.0 12 | 13 | com.didiglobal.sds 14 | sds-spring-boot-starter 15 | 16 | https://github.com/didi/sds 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter 22 | 23 | 24 | 25 | com.didiglobal.sds 26 | sds-spring-boot-autoconfigure 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /sds-front/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not ie <= 8 4 | -------------------------------------------------------------------------------- /sds-front/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential' 8 | ], 9 | rules: { 10 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 11 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 12 | }, 13 | parserOptions: { 14 | parser: 'babel-eslint' 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sds-front/README.md: -------------------------------------------------------------------------------- 1 | # sds 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run dev 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Run your unit tests 24 | ``` 25 | npm run test:unit 26 | ``` 27 | -------------------------------------------------------------------------------- /sds-front/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /sds-front/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "node version: "`node --version` 4 | echo "npm version: "`npm -version` 5 | 6 | npm install 7 | npm run build -------------------------------------------------------------------------------- /sds-front/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "opensds", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vue-cli-service serve --watch", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint", 9 | "test:unit": "vue-cli-service test:unit" 10 | }, 11 | "dependencies": { 12 | "echarts": "^4.2.0-rc.1", 13 | "element-ui": "^2.4.7", 14 | "vue": "^2.5.17", 15 | "vue-echarts": "^4.0.4", 16 | "vue-router": "^3.0.1", 17 | "vuex": "^3.0.1", 18 | "whatwg-fetch": "^3.0.0" 19 | }, 20 | "devDependencies": { 21 | "@vue/cli-plugin-babel": "^3.0.1", 22 | "@vue/cli-plugin-eslint": "^3.0.1", 23 | "@vue/cli-plugin-unit-mocha": "^3.0.1", 24 | "@vue/cli-service": "^3.0.1", 25 | "@vue/test-utils": "^1.0.0-beta.20", 26 | "chai": "^4.1.2", 27 | "node-sass": "^4.9.0", 28 | "sass-loader": "^7.0.1", 29 | "vue-template-compiler": "^2.5.17" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sds-front/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | com.didiglobal.sds 8 | sds-base 9 | 1.0.1-SNAPSHOT 10 | 11 | 12 | 4.0.0 13 | jar 14 | 15 | sds-front 16 | sds-front 17 | 18 | 19 | sds-front 20 | 21 | 22 | org.codehaus.mojo 23 | exec-maven-plugin 24 | 25 | 26 | npm-build 27 | validate 28 | 29 | exec 30 | 31 | 32 | bash 33 | 34 | -e 35 | build.sh 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /sds-front/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /sds-front/public/imgs/kd09dBTlVw5uaosvhLS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/sds/ff4571c6123f8a7223a0c5dfc70198c0a50097dc/sds-front/public/imgs/kd09dBTlVw5uaosvhLS.png -------------------------------------------------------------------------------- /sds-front/public/imgs/sds2.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/sds/ff4571c6123f8a7223a0c5dfc70198c0a50097dc/sds-front/public/imgs/sds2.0.png -------------------------------------------------------------------------------- /sds-front/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | SDS服务降级系统2.0 10 | 11 | 12 | 15 |

16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /sds-front/src/api/common.js: -------------------------------------------------------------------------------- 1 | export default { 2 | appVersion: '1.0.0', 3 | currentLocation: location.pathname 4 | } -------------------------------------------------------------------------------- /sds-front/src/api/login.js: -------------------------------------------------------------------------------- 1 | import utils from '../utils/utils'; 2 | 3 | // 根据环境设置SSO地址 4 | const ssoApiHost = (() => { 5 | switch (utils.getEnv()) { 6 | case "online": 7 | return 'http://mis.diditaxi.com.cn/auth'; 8 | 9 | default: 10 | return 'http://mis-test.diditaxi.com.cn/auth'; 11 | } 12 | })(); 13 | const ssoHost = (() => { 14 | switch (utils.getEnv()) { 15 | case "online": 16 | return 'https://star.xiaojukeji.com/data/ssologinweb.node'; 17 | 18 | default: 19 | return 'http://page-daily.kuaidadi.com/data/ssologinweb.node'; 20 | } 21 | })(); 22 | const appId = (() => { 23 | switch (utils.getEnv()) { 24 | case "online": 25 | return 2260; 26 | 27 | case "preonline": 28 | return 2519; 29 | 30 | case "stable": 31 | return 2260; 32 | 33 | case "local": 34 | return 2518; 35 | } 36 | })(); 37 | 38 | // 配置公有Ajax 39 | const CommonAjax = (url, type, params) => { 40 | return new Promise((resolve, reject) => { 41 | $.ajax({ 42 | url: url, 43 | type: type, 44 | data: params, 45 | success: (data) => { 46 | resolve(data) 47 | }, 48 | error: (err) => { 49 | reject(err) 50 | } 51 | }) 52 | }) 53 | } 54 | 55 | export default { 56 | checkCode: (params) => { 57 | return CommonAjax(ssoHost, 'POST', Object.assign({ 58 | apiName: 'checkCode' 59 | }, params)) 60 | }, 61 | checkTicket: (params) => { 62 | return CommonAjax(ssoHost, 'POST', Object.assign({ 63 | apiName: 'checkTicket' 64 | }, params)) 65 | }, 66 | getUserInfo: (params) => { 67 | return CommonAjax(ssoHost, 'POST', Object.assign({ 68 | apiName: 'getUserInfo' 69 | }, params)) 70 | }, 71 | loginInitData: { 72 | ssoApiHost, 73 | ssoHost, 74 | appId 75 | } 76 | } -------------------------------------------------------------------------------- /sds-front/src/assets/img/SDS2.0-dev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/sds/ff4571c6123f8a7223a0c5dfc70198c0a50097dc/sds-front/src/assets/img/SDS2.0-dev.png -------------------------------------------------------------------------------- /sds-front/src/assets/img/SDS2.0-online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/sds/ff4571c6123f8a7223a0c5dfc70198c0a50097dc/sds-front/src/assets/img/SDS2.0-online.png -------------------------------------------------------------------------------- /sds-front/src/assets/img/SDS2.0-pre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/sds/ff4571c6123f8a7223a0c5dfc70198c0a50097dc/sds-front/src/assets/img/SDS2.0-pre.png -------------------------------------------------------------------------------- /sds-front/src/assets/img/logo-single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/sds/ff4571c6123f8a7223a0c5dfc70198c0a50097dc/sds-front/src/assets/img/logo-single.png -------------------------------------------------------------------------------- /sds-front/src/components/common/aside/aside.scss: -------------------------------------------------------------------------------- 1 | .aside { 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | height: 100%; 6 | background-color: rgb(32, 34, 42); 7 | .el-menu { 8 | border-right: none 9 | } 10 | .logo { 11 | height: 70px; 12 | line-height: 70px; 13 | background-color: rgb(32, 34, 42); 14 | text-align: center; 15 | color: #fff; 16 | box-shadow: 0 1px 2px 0 rgba(0,0,0,.15); 17 | .text-span { 18 | color: #d4a266; 19 | display: block; 20 | .logo-img-big { 21 | max-width: 156px; 22 | margin-left: -20px; 23 | height: auto; 24 | vertical-align: middle; 25 | transition: all .3s ease-in-out; 26 | } 27 | } 28 | .img-span { 29 | display: block; 30 | .logo-img { 31 | max-width: 25px; 32 | vertical-align: middle; 33 | transition: all .3s ease-in-out; 34 | } 35 | .small-img { 36 | max-width: 55px; 37 | } 38 | } 39 | } 40 | .el-menu-vertical:not(.el-menu--collapse) { 41 | width: 220px; 42 | } 43 | } 44 | .el-menu-item i, .el-submenu i { 45 | margin-right: 5px; 46 | width: 24px; 47 | text-align: center; 48 | font-size: 18px; 49 | vertical-align: middle; 50 | } 51 | -------------------------------------------------------------------------------- /sds-front/src/components/common/building/building.scss: -------------------------------------------------------------------------------- 1 | .building { 2 | .building-txt { 3 | font-size: 45px; 4 | font-weight: bold; 5 | color: rgb(212, 162, 102); 6 | text-align: center; 7 | border: 4px solid; 8 | line-height: 400px; 9 | } 10 | } -------------------------------------------------------------------------------- /sds-front/src/components/common/building/building.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 27 | -------------------------------------------------------------------------------- /sds-front/src/components/common/content/content.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/sds/ff4571c6123f8a7223a0c5dfc70198c0a50097dc/sds-front/src/components/common/content/content.scss -------------------------------------------------------------------------------- /sds-front/src/components/common/content/content.vue: -------------------------------------------------------------------------------- 1 | 8 | 11 | 33 | -------------------------------------------------------------------------------- /sds-front/src/components/common/footer/footer.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/sds/ff4571c6123f8a7223a0c5dfc70198c0a50097dc/sds-front/src/components/common/footer/footer.scss -------------------------------------------------------------------------------- /sds-front/src/components/common/footer/footer.vue: -------------------------------------------------------------------------------- 1 | 8 | 11 | -------------------------------------------------------------------------------- /sds-front/src/components/common/header/header.scss: -------------------------------------------------------------------------------- 1 | .el-header { 2 | position: fixed; 3 | top: 0; 4 | left: 220px; 5 | right: 0; 6 | padding: 0; 7 | z-index: 1; 8 | height: 50px !important; 9 | background-color: #ffffff; 10 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05); 11 | transition: all .3s ease-in-out; 12 | 13 | .header-controller { 14 | overflow: hidden; 15 | padding: 0 15px; 16 | line-height: 45px; 17 | 18 | ul { 19 | font-size: 0; 20 | 21 | li { 22 | display: inline-block; 23 | 24 | a { 25 | display: inline-block; 26 | vertical-align: middle; 27 | margin: 0 15px; 28 | color: #333333; 29 | font-size: 16px; 30 | font-weight: bold; 31 | border-top: 2px solid #ffffff; 32 | transition: all .6s; 33 | 34 | &:hover { 35 | border-top: 2px solid #333333; 36 | } 37 | } 38 | 39 | span { 40 | display: inline-block; 41 | vertical-align: middle; 42 | } 43 | } 44 | } 45 | 46 | .env-tag { 47 | font-size: 16px; 48 | margin-right: 2em; 49 | color: indianred; 50 | font-weight: bold; 51 | } 52 | 53 | .hd-ct-left { 54 | float: left; 55 | 56 | .search-input { 57 | width: 150px; 58 | height: 30px; 59 | font-size: 14px; 60 | color: #000000; 61 | font-weight: normal; 62 | display: inline-block; 63 | vertical-align: middle; 64 | padding-left: 10px; 65 | border: none; 66 | outline: none; 67 | } 68 | } 69 | 70 | .hd-ct-right { 71 | float: right; 72 | 73 | .iconfont { 74 | margin: 0; 75 | border-top: none; 76 | } 77 | 78 | .user-name, .adSys-down { 79 | font-size: 14px; 80 | font-weight: normal; 81 | } 82 | 83 | .user-name { 84 | padding: 0 5px; 85 | } 86 | } 87 | 88 | } 89 | 90 | .bread-crumb { 91 | padding: 0 15px; 92 | background-color: #ffffff; 93 | 94 | .el-breadcrumb { 95 | line-height: 50px; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /sds-front/src/components/home/appList/appList.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/didi/sds/ff4571c6123f8a7223a0c5dfc70198c0a50097dc/sds-front/src/components/home/appList/appList.scss -------------------------------------------------------------------------------- /sds-front/src/components/home/appList/appList.vue: -------------------------------------------------------------------------------- 1 | 47 | 50 | 79 | -------------------------------------------------------------------------------- /sds-front/src/components/home/echartDemo/echartDemo.scss: -------------------------------------------------------------------------------- 1 | #myChart { 2 | margin-top: 30px; 3 | padding: 10px; 4 | border: 1px solid #ccc; 5 | height: 300px; 6 | } -------------------------------------------------------------------------------- /sds-front/src/components/home/echartDemo/echartDemo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 43 | -------------------------------------------------------------------------------- /sds-front/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import ElementUI from 'element-ui'; 3 | import 'element-ui/lib/theme-chalk/index.css'; 4 | import echarts from 'echarts' 5 | import App from './App.vue' 6 | import router from './router' 7 | import store from './store' 8 | import utils from './utils/utils' 9 | import DowngradeMonitor from "./views/DowngradeMonitor"; 10 | 11 | window.eventHub = new Vue(); 12 | 13 | Vue.use(ElementUI); 14 | Vue.config.productionTip = false; 15 | Vue.prototype.$echarts = echarts; 16 | 17 | // 路由拦截器 18 | // router.beforeEach((to, from, next) => { 19 | // // 判断是否登录过 TODO: 校验ticket是否失效 20 | // if (utils.getCookie('userInfo')) { 21 | // if (!store.getters['user/ticket']) { 22 | // let info = JSON.parse(utils.getCookie('userInfo')); 23 | // info.username_zh = decodeURI(info.username_zh); 24 | // store.commit('user/setUser', info); 25 | // } 26 | // next() 27 | // } else { 28 | // store.dispatch("user/login") 29 | // } 30 | // }) 31 | 32 | if (window.location.hash.startsWith('#/monitor/')) { 33 | console.log("是Monitor哒!!!"); 34 | new Vue({ 35 | router, 36 | store, 37 | render: h => h(DowngradeMonitor) 38 | }).$mount('#app') 39 | } else { 40 | new Vue({ 41 | router, 42 | store, 43 | render: h => h(App) 44 | }).$mount('#app') 45 | } 46 | 47 | -------------------------------------------------------------------------------- /sds-front/src/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import ApplicationGroup from './views/ApplicationGroup.vue' 4 | import ApplyName from './views/ApplyName.vue' 5 | import SdsScheme from './views/SdsScheme.vue' 6 | import DemotePoint from './views/DemotePoint.vue' 7 | import DemotePointResponse from "./views/DemotePointResponse.vue"; 8 | import SettingUp from './views/SettingUp.vue' 9 | import DowngradeChart from './views/DowngradeChart.vue' 10 | 11 | Vue.use(Router); 12 | 13 | export default new Router({ 14 | // mode: "history", 15 | base: process.env.BASE_URL, 16 | routes: [ 17 | { 18 | path: "/about", 19 | name: "关于我们", 20 | component: () => import("./views/About.vue") 21 | }, 22 | { 23 | path: "/applicationGroup", 24 | name: "应用组", 25 | component: ApplicationGroup 26 | }, 27 | { 28 | path: "/applyName", 29 | name: "应用", 30 | component: ApplyName 31 | }, 32 | { 33 | path: "/sdsScheme", 34 | name: "降级预案", 35 | component: SdsScheme 36 | }, 37 | { 38 | path: "/demotePoint", 39 | name: "降级点策略", 40 | component: DemotePoint 41 | }, 42 | { 43 | path: "/demotePointResponse", 44 | name: "降级返回值", 45 | component: DemotePointResponse 46 | }, 47 | { 48 | path: "/settingUp", 49 | name: "设置", 50 | component: SettingUp 51 | }, 52 | { 53 | path: "/downgradeChart", 54 | name: "监控大盘", 55 | component: DowngradeChart 56 | }, 57 | { 58 | path: "/", 59 | name: "首页", 60 | redirect: "/applicationGroup" 61 | } 62 | ] 63 | }); 64 | -------------------------------------------------------------------------------- /sds-front/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import user from './modules/user' 4 | 5 | Vue.use(Vuex) 6 | 7 | const debug = process.env.NODE_ENV !== 'production'; 8 | 9 | export default new Vuex.Store({ 10 | modules: { 11 | user 12 | }, 13 | strict: debug, 14 | plugins: [] 15 | }) -------------------------------------------------------------------------------- /sds-front/src/utils/fetch.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch' 2 | 3 | // 定义公有头部 4 | const commonHeader = { 5 | 'Accept': 'application/json', 6 | 'Content-Type': 'application/json' 7 | } 8 | 9 | export default { 10 | /** 11 | * 基于 fetch 封装的 GET请求 12 | * @param url 13 | * @param params {} 14 | * @param headers 15 | * @returns {Promise} 16 | */ 17 | get(url, params, headers) { 18 | if (params) { 19 | let paramsArray = []; 20 | //encodeURIComponent 21 | Object.keys(params).forEach(key => paramsArray.push(key + '=' + params[key])) 22 | if (url.search(/\?/) === -1) { 23 | url += '?' + paramsArray.join('&') 24 | } else { 25 | url += '&' + paramsArray.join('&') 26 | } 27 | } 28 | return new Promise(function (resolve, reject) { 29 | fetch(url, { 30 | method: 'GET', 31 | credentials: 'include', 32 | headers: headers || commonHeader, 33 | }) 34 | .then((response) => { 35 | if (response.ok) { 36 | return response.json(); 37 | } else { 38 | reject({status: response.status}) 39 | } 40 | }) 41 | .then((response) => { 42 | resolve(response); 43 | }) 44 | .catch((err) => { 45 | reject({status: -1}); 46 | }) 47 | }) 48 | }, 49 | /** 50 | * 基于 fetch 封装的 POST请求 FormData 表单数据 51 | * @param url 52 | * @param formData 53 | * @param headers 54 | * @returns {Promise} 55 | */ 56 | post(url, formData, headers) { 57 | return new Promise(function (resolve, reject) { 58 | fetch(url, { 59 | method: 'POST', 60 | credentials: 'include', 61 | headers: headers || commonHeader, 62 | body: JSON.stringify(formData), 63 | }) 64 | .then((response) => { 65 | if (response.ok) { 66 | return response.json(); 67 | } else { 68 | reject({status: response.status}) 69 | } 70 | }) 71 | .then((response) => { 72 | resolve(response); 73 | }) 74 | .catch((err) => { 75 | reject({status: -1}); 76 | }) 77 | }) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /sds-front/src/utils/timeFormat.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 时间格式化 3 | */ 4 | function SimpleDateFormat(pattern) { 5 | const fmt = {}; 6 | fmt.pattern = pattern; 7 | 8 | fmt.parse = function (source) { 9 | try { 10 | return new Date(source); 11 | } catch (e) { 12 | console.log("字符串 " + source + " 转时间格式失败!"); 13 | return null; 14 | } 15 | }; 16 | 17 | fmt.format = function (date) { 18 | if (typeof (date) == "undefined" || date == null || date === "") { 19 | return ""; 20 | } 21 | 22 | try { 23 | date = new Date(date); 24 | } catch (e) { 25 | console.log("时间 " + date + " 格式化失败!"); 26 | return ""; 27 | } 28 | 29 | let strTime = this.pattern;//时间表达式的正则 30 | 31 | const o = { 32 | "M+": date.getMonth() + 1, //月份 33 | "d+": date.getDate(), //日 34 | "H+": date.getHours(), //小时 35 | "m+": date.getMinutes(), //分 36 | "s+": date.getSeconds(), //秒 37 | "q+": Math.floor((date.getMonth() + 3) / 3), //季度 38 | "S": date.getMilliseconds() //毫秒 39 | }; 40 | 41 | if (/(y+)/.test(strTime)) { 42 | strTime = strTime 43 | .replace(RegExp.$1, (date.getFullYear() + "") 44 | .substr(4 - RegExp.$1.length)); 45 | } 46 | for (const k in o) { 47 | if (new RegExp("(" + k + ")").test(strTime)) { 48 | strTime = strTime.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); 49 | } 50 | } 51 | 52 | return strTime; 53 | }; 54 | return fmt; 55 | } 56 | 57 | export default { 58 | timeFormat(time) { 59 | return this.utcTimeFormat(time); 60 | }, 61 | utcTimeFormat(time) { 62 | const format = SimpleDateFormat('yyyy-MM-dd HH:mm:ss'); 63 | return format.format(new Date(time)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sds-front/src/utils/utils.js: -------------------------------------------------------------------------------- 1 | export default { 2 | getEnv() { 3 | switch (location.hostname) { 4 | case "opensds.xiaojukeji.com": 5 | return "online"; 6 | 7 | case "10.89.191.50": 8 | return "preonline"; 9 | 10 | case "127.0.0.1": 11 | return "stable"; 12 | 13 | default: 14 | return "local"; 15 | } 16 | }, 17 | getQueryString(url, name) { 18 | let lets = {}; 19 | url.replace(/[?&]+([^=&]+)=([^&#]*)/gi, (m, key, value) => { 20 | lets[key] = value; 21 | }); 22 | return name ? lets[name] : lets; 23 | }, 24 | setCookie(key, value) { 25 | let exdate = new Date(); 26 | exdate.setTime(exdate.getTime() + 24 * 60 * 60 * 1000); 27 | //字符串拼接cookie 28 | window.document.cookie = key + "=" + value + ";path=/;expires=" + exdate.toGMTString(); 29 | }, 30 | getCookie(param) { 31 | let c_param = ''; 32 | if (document.cookie.length > 0) { 33 | let arr = document.cookie.split('; '); 34 | for (let i = 0; i < arr.length; i++) { 35 | let arr2 = arr[i].split('='); 36 | //判断查找相对应的值 37 | if (arr2[0] == param) { 38 | c_param = arr2[1]; 39 | } 40 | } 41 | return c_param; 42 | } 43 | }, 44 | delCookie(name) { 45 | if (Array.isArray(name)) { 46 | for (let i = 0; i < name.length; i++) { 47 | const element = name[i]; 48 | let exp = new Date(); 49 | exp.setTime(exp.getTime() - 1); 50 | let cval = this.getCookie(element); 51 | cval != null ? (document.cookie = element + "=" + cval + ";expires=" + exp.toGMTString()) : false; 52 | } 53 | } else { 54 | let exp = new Date(); 55 | exp.setTime(exp.getTime() - 1); 56 | let cval = this.getCookie(name); 57 | cval != null ? (document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString()) : false; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /sds-front/src/views/About.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /sds-front/src/views/DowngradeChart.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /sds-front/src/views/SettingUp.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /sds-front/tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | mocha: true 4 | } 5 | } -------------------------------------------------------------------------------- /sds-front/tests/unit/example.spec.js: -------------------------------------------------------------------------------- 1 | import {expect} from 'chai' 2 | import {shallowMount} from '@vue/test-utils' 3 | import HelloWorld from '@/components/HelloWorld.vue' 4 | 5 | describe('HelloWorld.vue', () => { 6 | it('renders props.msg when passed', () => { 7 | const msg = 'new message' 8 | const wrapper = shallowMount(HelloWorld, { 9 | propsData: { msg } 10 | }) 11 | expect(wrapper.text()).to.include(msg) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /sds-front/vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | module.exports = { 4 | outputDir: path.resolve(__dirname, "target/static"), 5 | devServer: { 6 | port: 8080, 7 | host: "localhost", 8 | https: false, 9 | open: true, 10 | proxy: { 11 | "/": { 12 | target: "http://localhost:8887", //设置调用的接口域名和端口 13 | changeOrigin: false, //是否跨域 14 | ws: false, 15 | } 16 | } 17 | }, 18 | configureWebpack: { 19 | devtool: "eval-source-map", // https://github.com/vuejs/vue-cli/issues/4572 20 | } 21 | }; --------------------------------------------------------------------------------