Explorar o código

优化生成恒大授权码的接口

houweiyu %!s(int64=4) %!d(string=hai) anos
pai
achega
3330254e02

+ 19 - 0
pom.xml

@@ -128,6 +128,25 @@
         </dependency>
 
         <dependency>
+            <groupId>com.netflix.hystrix</groupId>
+            <artifactId>hystrix-core</artifactId>
+            <version>1.5.12</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/com.netflix.hystrix/hystrix-javanica -->
+        <dependency>
+            <groupId>com.netflix.hystrix</groupId>
+            <artifactId>hystrix-javanica</artifactId>
+            <version>1.5.12</version>
+        </dependency>
+        <!-- http://mvnrepository.com/artifact/com.netflix.hystrix/hystrix-metrics-event-stream -->
+        <dependency>
+            <groupId>com.netflix.hystrix</groupId>
+            <artifactId>hystrix-metrics-event-stream</artifactId>
+            <version>1.5.12</version>
+        </dependency>
+
+
+        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-tomcat</artifactId>
             <scope>provided</scope>

+ 28 - 0
src/main/java/fcb/project/manager/base/config/HystrixConfig.java

@@ -0,0 +1,28 @@
+package fcb.project.manager.base.config;
+
+import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
+import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect;
+import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class HystrixConfig {
+
+    @Bean
+    @HystrixProperty(name = "circuitBreaker.enabled", value = "true")
+    public HystrixCommandAspect hystrixCommandAspect() {
+        return new HystrixCommandAspect();
+    }
+
+    /**
+     * Send stream message to Hystrix-dashboard
+     */
+    @Bean
+    public ServletRegistrationBean hystrixMetricsStreamServlet() {
+        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
+        registrationBean.addUrlMappings("/hystrix.stream");
+        return registrationBean;
+    }
+}

+ 35 - 4
src/main/java/fcb/project/manager/base/utils/FcbUtils.java

@@ -2,31 +2,55 @@ package fcb.project.manager.base.utils;
 
 import com.alibaba.fastjson.JSON;
 import fdage.back.sdk.base.entity.Result;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.time.Duration;
 import java.time.Instant;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 /**
  * 2 * @Author: Abner
  * 3 * @Date: 2021/1/18 9:11
  * 4
  */
+@Service
+@Log4j2
 public class FcbUtils {
 
 
-    public static Result<Object> getFcbSign(Map<String , Object> params
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+
+    public  Result<Object> getFcbSign(Map<String , Object> params
             , String fcbClientSecret , String fcbClientCode){
 
         if(CollectionUtils.isEmpty(params)){
             return Result.failure("入参不能为空");
         }
+        long timeStamp = Instant.now().getEpochSecond();
+        Instant stepOneStart = Instant.now();
+        String redisKey = JSON.toJSONString(params) + timeStamp;
+        if(redisTemplate.hasKey(redisKey)){
+            log.info("缓存中存在,直接返回");
+            Map<String , Object> resultMp  = (Map<String, Object>) redisTemplate.opsForValue().get(redisKey);
+            return Result.success(resultMp);
+
+        }
+        Instant stepOneEnd = Instant.now();
+        long stepOneDuration = Duration.between(stepOneStart , stepOneEnd).toMillis();
+        log.info("步骤1耗时:{}" , stepOneDuration);
+        Instant stepTwoStart = Instant.now();
         for (Map.Entry entry : params.entrySet()) {
             //1、先剔除value值为null的键值对
             if(null  == entry.getValue()){
@@ -34,22 +58,29 @@ public class FcbUtils {
             }
         }
         //2、新增房车宝的client_secret作为噪点
-        long timeStamp = Instant.now().getEpochSecond();
         params.put("client_secret" , fcbClientSecret);
         params.put("client_code" , fcbClientCode);
         params.put("req_time" , timeStamp);
         params = DataUtils.sortMapByKey(params);
-        StringBuilder stringBuilder = new StringBuilder();
+        Instant stepTwoEnd = Instant.now();
+        long stepTwoDuration = Duration.between(stepTwoStart , stepTwoEnd).toMillis();
+        log.info("步骤2耗时:{}" , stepTwoDuration);
 
+        Instant stepThreeStart = Instant.now();
+        StringBuilder stringBuilder = new StringBuilder();
         for ( Map.Entry entry : params.entrySet()) {
             stringBuilder.append(entry.getValue());
         }
-
         //3、生成MD5密文,然后转成小写字母
         String md5EncryptionStr = DataUtils.md5Encryption(stringBuilder.toString());
         Map<String , Object> resultMap = new HashMap<>();
         resultMap.put("authcode" , md5EncryptionStr);
         resultMap.put("timeStamp" , timeStamp);
+        //缓存一秒
+        redisTemplate.opsForValue().set(redisKey , JSON.toJSONString(resultMap) , 1000 , TimeUnit.MILLISECONDS);
+        Instant stepThreeEnd = Instant.now();
+        long stepThreeDuration = Duration.between(stepThreeStart , stepThreeEnd).toMillis();
+        log.info("步骤3耗时:{}" , stepThreeDuration);
         return Result.success(resultMap);
 
     }

+ 33 - 1
src/main/java/fcb/project/manager/core/controller/ApiQueryHouseController.java

@@ -1,10 +1,14 @@
 package fcb.project.manager.core.controller;
 
+import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
+import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
+import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
 import fcb.project.manager.base.utils.FcbUtils;
 import fdage.back.sdk.base.entity.Result;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -22,6 +26,7 @@ import java.util.Map;
 @Log4j2
 @RestController
 @RequestMapping("fcb/project/api/query")
+@DefaultProperties(defaultFallback = "defaultFail")
 public class ApiQueryHouseController {
 
 
@@ -31,12 +36,39 @@ public class ApiQueryHouseController {
     @Value("${fcb.client.code}")
     private String fcbClientCode;
 
+    @Autowired
+    private FcbUtils fcbUtils;
 
+
+    @HystrixCommand(commandProperties = {
+            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500"),
+            // 设置统计窗口的桶数量
+            @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
+            // 设置统计窗口的总时间。每个桶时间 = 总时间 / 桶数量。
+            // 该案例中每个桶时间 = 10000 / 10(ms) = 1000ms
+            // 每个bucket包含success,failure,timeout,rejection的次数的统计信息
+            @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000")
+    },
+            threadPoolProperties = {
+                    @HystrixProperty(name = "coreSize", value = "300"),
+                    // BlockingQueue的最大队列数,当设为-1,会使用SynchronousQueue,值为正时使用LinkedBlockingQueue。
+                    @HystrixProperty(name = "maxQueueSize", value = "200"),
+                    // 设置存活时间,单位分钟。如果coreSize小于maximumSize,那么该属性控制一个线程从实用完成到被释放的时间.
+                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
+                    // 设置队列拒绝的阈值,即使maxQueueSize还没有达到
+                    @HystrixProperty(name = "queueSizeRejectionThreshold", value = "15"),
+                    @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
+                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000")
+            })
     @ApiOperation(value = "获取房车宝的签名")
     @PostMapping("/authCode")
     public Result<Object> getFcbSign(@RequestBody Map<String, Object> params) {
-        return FcbUtils.getFcbSign(params, fcbClientSecret, fcbClientCode);
+        return fcbUtils.getFcbSign(params, fcbClientSecret, fcbClientCode);
     }
 
 
+    private  Result<Object> defaultFail() {
+        log.info("触发了熔断器,这里给出默认返回");
+        return  Result.failure(3444 , "网络拥挤,请稍后再试");
+    }
 }

+ 8 - 4
src/main/resources/application-dev.properties

@@ -16,15 +16,19 @@ swagger.page.version=1.0
 swagger.page.desc=设计到房源api、楼盘项目管理、审核流程业务逻辑的接口
 swagger.page.packagePath=fcb.project.manager
 
-spring.redis.cluster.max-redirects=3
-spring.redis.cluster.nodes=8.135.107.23:30064
+#spring.redis.cluster.max-redirects=3
+#spring.redis.cluster.nodes=8.135.107.23:30064
+#redis
+spring.redis.database=0
+spring.redis.host=127.0.0.1
+spring.redis.port=6379
+spring.redis.password=
 spring.redis.timeout=5000ms
 spring.redis.jedis.pool.max-active=8
 spring.redis.jedis.pool.max-idle=8
 spring.redis.jedis.pool.max-wait=-1
 spring.redis.jedis.pool.min-idle=0
-spring.redis.database=0
-spring.redis.password=
+
 
 
 fcb.client.code=zxd9WS2twZ3J4DuhJ2r3y6qz1OZ2hMbr

+ 2 - 2
src/main/resources/application.properties

@@ -1,10 +1,10 @@
 
 
-spring.profiles.active=prod
+#spring.profiles.active=prod
 #spring.profiles.active=dev
 #spring.profiles.active=uat
 #sit环境,这里使用了test因为sdk的swagger使用的是test,所以这里使用sit
-#spring.profiles.active=test
+spring.profiles.active=test
 
 #应用名
 spring.application.name=fbc-project-manager