丁云鹏 11 hónapja
commit
95bb883561
100 módosított fájl, 3674 hozzáadás és 0 törlés
  1. 203 0
      long-article-recommend-service/long-article-recommend-service.iml
  2. 119 0
      long-article-recommend-service/pom.xml
  3. 32 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/Application.java
  4. 40 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/CommonThreadPoolExecutor.java
  5. 17 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/HttpPoolFactory.java
  6. 49 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/ThreadPoolFactory.java
  7. 63 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/config/RedisTemplateConfig.java
  8. 17 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/Content.java
  9. 17 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/RecommendRequest.java
  10. 17 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/RecommendResponse.java
  11. 28 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/AIGCRemoteService.java
  12. 81 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/NLPRemoteService.java
  13. 22 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/RecommendParam.java
  14. 58 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/RecommendService.java
  15. 23 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/ServiceBeanFactory.java
  16. 17 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/WarmUpService.java
  17. 41 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/FilterParam.java
  18. 17 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/FilterResult.java
  19. 74 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/FilterService.java
  20. 8 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/FilterStrategy.java
  21. 22 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/strategy/SimilarityStrategy.java
  22. 72 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/odps/ODPSManager.java
  23. 14 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankParam.java
  24. 17 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankResult.java
  25. 135 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankRouter.java
  26. 27 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankService.java
  27. 16 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/FilterParamFactory.java
  28. 11 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallParam.java
  29. 27 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallResult.java
  30. 86 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallService.java
  31. 12 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallStrategy.java
  32. 38 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/strategy/DefaultRecallStrategy.java
  33. 59 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/CommonCollectionUtils.java
  34. 65 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/DateUtils.java
  35. 96 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/HttpClientFactory.java
  36. 49 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/JSONUtils.java
  37. 52 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/TraceUtils.java
  38. 42 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/ControllerAspect.java
  39. 24 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/GlobalExceptionHandler.java
  40. 18 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/HealthCheckController.java
  41. 29 0
      long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/RecommendV2Controller.java
  42. 136 0
      long-article-recommend-service/src/main/resources/application-dev.yml
  43. 131 0
      long-article-recommend-service/src/main/resources/application-pre.yml
  44. 131 0
      long-article-recommend-service/src/main/resources/application-prod.yml
  45. 132 0
      long-article-recommend-service/src/main/resources/application-test.yml
  46. 61 0
      long-article-recommend-service/src/main/resources/application.yml
  47. 328 0
      long-article-recommend-service/src/main/resources/logback.xml
  48. 304 0
      long-article-recommend-service/src/test/java/com/tzld/piaoquan/recommend/test/merger/MergeUtilsTest.java
  49. 0 0
      long-article-recommend-service/target/classes/20240609_bucket_274.txt
  50. 136 0
      long-article-recommend-service/target/classes/application-dev.yml
  51. 131 0
      long-article-recommend-service/target/classes/application-pre.yml
  52. 131 0
      long-article-recommend-service/target/classes/application-prod.yml
  53. 132 0
      long-article-recommend-service/target/classes/application-test.yml
  54. 61 0
      long-article-recommend-service/target/classes/application.yml
  55. 6 0
      long-article-recommend-service/target/classes/attention_config.conf
  56. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/Application.class
  57. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/CommonThreadPoolExecutor.class
  58. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/RecommendLoghubAppender.class
  59. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/RecommendLoghubAppenderCallback.class
  60. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/ThreadPoolFactory.class
  61. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/base/Constant.class
  62. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/base/RankItem.class
  63. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/base/VideoActionFeature.class
  64. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/enums/AppTypeEnum.class
  65. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/CustomMongoProperties.class
  66. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/FeatureRedisTemplateConfig.class
  67. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/FilterRedisTemplateConfig.class
  68. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/LongVideoRedisTemplateConfig.class
  69. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/MongoTemplateConfig.class
  70. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/RedisTemplateConfig.class
  71. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/VideoRedisTemplateConfig.class
  72. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/XxlJobConfig.class
  73. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/dataloader/FeatureConstructor.class
  74. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/dataloader/ItemFeatureToRedisLoader.class
  75. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/dataloader/OfflineAdOutSamplesLoader.class
  76. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/dataloader/UserFeatureToRedisLoader.class
  77. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/candidiate/Candidate.class
  78. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/candidiate/CandidateInfo.class
  79. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/candidiate/Entry.class
  80. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/candidiate/Queue.class
  81. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/candidiate/QueueName.class
  82. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/common/User.class
  83. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/common/UserAction.class
  84. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/common/UserAttention.class
  85. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/IndexCandidateQueue.class
  86. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/MergeRule.class
  87. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/MergeUtils.class
  88. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/SimilarityUtils.class
  89. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/SimpleMergeQueue.class
  90. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/StrategyQueue.class
  91. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/StrategyQueueConfig.class
  92. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/StrategyQueueInfo.class
  93. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/GBDTModel.class
  94. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/LRModel.class
  95. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/Model.class
  96. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/ModelManager.class
  97. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/OssConfig.class
  98. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/ThompsonSamplingModel.class
  99. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/recaller/AbstractFilter.class
  100. BIN
      long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/recaller/BaseRecaller.class

+ 203 - 0
long-article-recommend-service/long-article-recommend-service.iml

@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+  <component name="FacetManager">
+    <facet type="web" name="Web">
+      <configuration>
+        <webroots />
+        <sourceRoots>
+          <root url="file://$MODULE_DIR$/src/main/java" />
+          <root url="file://$MODULE_DIR$/src/main/resources" />
+        </sourceRoots>
+      </configuration>
+    </facet>
+    <facet type="jpa" name="JPA">
+      <configuration>
+        <setting name="validation-enabled" value="true" />
+        <setting name="provider-name" value="Hibernate" />
+        <datasource-mapping />
+        <naming-strategy-map />
+      </configuration>
+    </facet>
+    <facet type="Spring" name="Spring">
+      <configuration />
+    </facet>
+  </component>
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
+    <output url="file://$MODULE_DIR$/target/classes" />
+    <output-test url="file://$MODULE_DIR$/target/test-classes" />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/${project.build.directory}/classes" />
+      <excludeFolder url="file://$MODULE_DIR$/${project.build.directory}/test-classes" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: org.apache.commons:commons-pool2:2.9.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.commons:commons-math3:3.6.1" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.11" level="project" />
+    <orderEntry type="library" name="Maven: com.aliyun.oss:aliyun-sdk-oss:3.15.1" level="project" />
+    <orderEntry type="library" name="Maven: org.jdom:jdom2:2.0.6" level="project" />
+    <orderEntry type="library" name="Maven: org.codehaus.jettison:jettison:1.1" level="project" />
+    <orderEntry type="library" name="Maven: com.aliyun:aliyun-java-sdk-core:4.5.10" level="project" />
+    <orderEntry type="library" name="Maven: commons-logging:commons-logging:1.2" level="project" />
+    <orderEntry type="library" name="Maven: javax.xml.bind:jaxb-api:2.3.1" level="project" />
+    <orderEntry type="library" name="Maven: javax.activation:javax.activation-api:1.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.jacoco:org.jacoco.agent:runtime:0.8.5" level="project" />
+    <orderEntry type="library" name="Maven: org.ini4j:ini4j:0.5.4" level="project" />
+    <orderEntry type="library" name="Maven: io.opentracing:opentracing-api:0.33.0" level="project" />
+    <orderEntry type="library" name="Maven: io.opentracing:opentracing-util:0.33.0" level="project" />
+    <orderEntry type="library" name="Maven: io.opentracing:opentracing-noop:0.33.0" level="project" />
+    <orderEntry type="library" name="Maven: com.aliyun:aliyun-java-sdk-ram:3.1.0" level="project" />
+    <orderEntry type="library" name="Maven: com.aliyun:aliyun-java-sdk-kms:2.11.0" level="project" />
+    <orderEntry type="library" name="Maven: com.aliyun.odps:odps-sdk-core:0.45.6-public" level="project" />
+    <orderEntry type="library" name="Maven: com.aliyun.odps:odps-sdk-commons:0.45.6-public" level="project" />
+    <orderEntry type="library" name="Maven: org.aspectj:aspectjrt:1.9.6" level="project" />
+    <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.15" level="project" />
+    <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-mapper-asl:1.9.13" level="project" />
+    <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-core-asl:1.9.13" level="project" />
+    <orderEntry type="library" name="Maven: org.antlr:antlr4:4.11.1" level="project" />
+    <orderEntry type="library" name="Maven: org.antlr:antlr4-runtime:4.11.1" level="project" />
+    <orderEntry type="library" name="Maven: org.antlr:antlr-runtime:3.5.3" level="project" />
+    <orderEntry type="library" name="Maven: org.antlr:ST4:4.3.4" level="project" />
+    <orderEntry type="library" name="Maven: org.abego.treelayout:org.abego.treelayout.core:1.0.3" level="project" />
+    <orderEntry type="library" name="Maven: org.glassfish:javax.json:1.1.4" level="project" />
+    <orderEntry type="library" name="Maven: com.ibm.icu:icu4j:71.1" level="project" />
+    <orderEntry type="library" name="Maven: com.google.guava:guava:29.0-jre" level="project" />
+    <orderEntry type="library" name="Maven: com.google.guava:failureaccess:1.0.1" level="project" />
+    <orderEntry type="library" name="Maven: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" />
+    <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.checkerframework:checker-qual:2.11.1" level="project" />
+    <orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.3.4" level="project" />
+    <orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.3" level="project" />
+    <orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.6" level="project" />
+    <orderEntry type="library" name="Maven: net.sourceforge.javacsv:javacsv:2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.xerial.snappy:snappy-java:1.1.10.3" level="project" />
+    <orderEntry type="library" name="Maven: org.lz4:lz4-pure-java:1.8.0" level="project" />
+    <orderEntry type="library" name="Maven: com.google.protobuf:protobuf-java:2.5.0" level="project" />
+    <orderEntry type="library" name="Maven: commons-io:commons-io:2.11.0" level="project" />
+    <orderEntry type="library" name="Maven: javax.mail:mail:1.4.7" level="project" />
+    <orderEntry type="library" name="Maven: javax.activation:activation:1.1" level="project" />
+    <orderEntry type="library" name="Maven: stax:stax-api:1.0.1" level="project" />
+    <orderEntry type="library" name="Maven: stax:stax:1.2.0" level="project" />
+    <orderEntry type="library" name="Maven: xpp3:xpp3:1.1.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.arrow:arrow-vector:4.0.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.arrow:arrow-format:4.0.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.arrow:arrow-memory-core:4.0.0" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.11.4" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.11.4" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.11.4" level="project" />
+    <orderEntry type="library" name="Maven: com.google.flatbuffers:flatbuffers-java:1.12.0" level="project" />
+    <orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-all:4.1.58.Final" level="project" />
+    <orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.27" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
+    <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.13.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.13.3" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.28" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.4.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.4.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.3" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.activation:jakarta.activation-api:1.2.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.18.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest:2.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.7.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.7.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.7.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-params:5.7.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.7.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.7.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:3.6.28" level="project" />
+    <orderEntry type="library" name="Maven: net.bytebuddy:byte-buddy:1.10.19" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.10.19" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:3.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-junit-jupiter:3.6.28" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-core:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.3.3" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.3.3" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.7.0" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-redis:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-redis:2.4.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-keyvalue:2.4.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-tx:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-oxm:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-aop:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: io.lettuce:lettuce-core:6.0.2.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-common:4.1.58.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.58.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.58.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.58.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.58.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.58.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.4.2" level="project" />
+    <orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.3" level="project" />
+    <orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.62" level="project" />
+    <orderEntry type="library" name="Maven: com.ctrip.framework.apollo:apollo-client:1.8.0" level="project" />
+    <orderEntry type="library" name="Maven: com.ctrip.framework.apollo:apollo-core:1.8.0" level="project" />
+    <orderEntry type="library" name="Maven: com.google.inject:guice:4.1.0" level="project" />
+    <orderEntry type="library" name="Maven: javax.inject:javax.inject:1" level="project" />
+    <orderEntry type="library" name="Maven: aopalliance:aopalliance:1.0" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.28" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.13" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.14" level="project" />
+    <orderEntry type="library" name="Maven: org.projectlombok:lombok:1.18.24" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.1" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.11.4" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.4" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.11.4" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.41" level="project" />
+    <orderEntry type="library" name="Maven: org.glassfish:jakarta.el:3.0.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.41" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-web:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-beans:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-context:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-expression:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-jpa:2.4.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-aop:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: org.aspectj:aspectjweaver:1.9.6" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.4.2" level="project" />
+    <orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.4.5" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.transaction:jakarta.transaction-api:1.3.3" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.persistence:jakarta.persistence-api:2.2.3" level="project" />
+    <orderEntry type="library" name="Maven: org.hibernate:hibernate-core:5.4.27.Final" level="project" />
+    <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.4.1.Final" level="project" />
+    <orderEntry type="library" name="Maven: org.javassist:javassist:3.27.0-GA" level="project" />
+    <orderEntry type="library" name="Maven: antlr:antlr:2.7.7" level="project" />
+    <orderEntry type="library" name="Maven: org.jboss:jandex:2.1.3.Final" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.5.1" level="project" />
+    <orderEntry type="library" name="Maven: org.dom4j:dom4j:2.1.3" level="project" />
+    <orderEntry type="library" name="Maven: org.hibernate.common:hibernate-commons-annotations:5.1.2.Final" level="project" />
+    <orderEntry type="library" name="Maven: org.glassfish.jaxb:jaxb-runtime:2.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.glassfish.jaxb:txw2:2.3.3" level="project" />
+    <orderEntry type="library" name="Maven: com.sun.istack:istack-commons-runtime:3.0.11" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: com.sun.activation:jakarta.activation:1.2.2" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-jpa:2.4.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:2.4.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-orm:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-aspects:5.3.3" level="project" />
+    <orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.47" level="project" />
+  </component>
+</module>

+ 119 - 0
long-article-recommend-service/pom.xml

@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.tzld.long.article</groupId>
+        <artifactId>long-article-recommend</artifactId>
+        <version>1.0.0</version>
+    </parent>
+    <artifactId>long-article-recommend-service</artifactId>
+    <name>long-article-recommend-service</name>
+    <description>long-article-recommend-service</description>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-pool2</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math3</artifactId>
+            <version>3.6.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.4</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>3.15.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.odps</groupId>
+            <artifactId>odps-sdk-core</artifactId>
+            <version>0.45.6-public</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.junit.vintage</groupId>
+                    <artifactId>junit-vintage-engine</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ctrip.framework.apollo</groupId>
+            <artifactId>apollo-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.18.24</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-collections4</artifactId>
+            <version>4.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+            <version>2.4.3</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+    </dependencies>
+
+
+    <build>
+        <finalName>long-article-recommend-service</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>com.tzld.long.article.recommend.server.Application</mainClass>
+                    <layout>ZIP</layout>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 32 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/Application.java

@@ -0,0 +1,32 @@
+package com.tzld.longarticle.recommend.server;
+
+// import com.tzld.piaoquan.recommend.feature.client.FeatureClient;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+
+/**
+ * https://github.com/grpc-swagger/grpc-swagger/blob/master/README_CN.md
+ */
+@SpringBootApplication(exclude = {
+        RedisReactiveAutoConfiguration.class
+})
+@ComponentScan({
+        "com.tzld.longarticle.recommend.server.service",
+        "com.tzld.longarticle.recommend.server.remote",
+        "com.tzld.longarticle.recommend.server.config",
+        "com.tzld.longarticle.recommend.server.web",
+})
+@EnableAspectJAutoProxy
+public class Application {
+    public static void main(String[] args) {
+        SpringApplication.run(Application.class, args);
+    }
+
+
+}
+

+ 40 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/CommonThreadPoolExecutor.java

@@ -0,0 +1,40 @@
+package com.tzld.longarticle.recommend.server.common;
+
+import org.slf4j.MDC;
+
+import java.util.Map;
+import java.util.concurrent.*;
+
+/**
+ * @author dyp
+ */
+public class CommonThreadPoolExecutor extends ThreadPoolExecutor {
+    public CommonThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
+    }
+
+    public CommonThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
+    }
+
+    public CommonThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
+    }
+
+    public CommonThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
+    }
+
+    @Override
+    public void execute(Runnable command) {
+        Map<String, String> mdcMap = MDC.getCopyOfContextMap();
+        super.execute(() -> {
+            if (mdcMap != null) {
+                MDC.setContextMap(mdcMap);
+            }
+            command.run();
+            MDC.clear();
+        });
+    }
+
+}

+ 17 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/HttpPoolFactory.java

@@ -0,0 +1,17 @@
+package com.tzld.longarticle.recommend.server.common;
+
+import com.tzld.longarticle.recommend.server.util.HttpClientFactory;
+import org.apache.http.impl.client.CloseableHttpClient;
+
+/**
+ * @author dyp
+ */
+public final class HttpPoolFactory {
+    private static CloseableHttpClient DEFAULT =
+            HttpClientFactory.create(1000, 1000, 200, 200, 0, 1000);
+
+    public static CloseableHttpClient defaultPool() {
+        return DEFAULT;
+    }
+
+}

+ 49 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/common/ThreadPoolFactory.java

@@ -0,0 +1,49 @@
+package com.tzld.longarticle.recommend.server.common;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author dyp
+ */
+public final class ThreadPoolFactory {
+    private final static ExecutorService DEFAULT = new CommonThreadPoolExecutor(
+            32,
+            128,
+            0L, TimeUnit.SECONDS,
+            new LinkedBlockingQueue<>(1000),
+            new ThreadFactoryBuilder().setNameFormat("DEFAULT-%d").build(),
+            new ThreadPoolExecutor.AbortPolicy());
+    public final static ExecutorService RECALL = new CommonThreadPoolExecutor(
+            32,
+            128,
+            0L, TimeUnit.SECONDS,
+            new LinkedBlockingQueue<>(1000),
+            new ThreadFactoryBuilder().setNameFormat("RecallService-%d").build(),
+            new ThreadPoolExecutor.AbortPolicy());
+    private final static ExecutorService FILTER = new CommonThreadPoolExecutor(
+            32,
+            128,
+            0L, TimeUnit.SECONDS,
+            new LinkedBlockingQueue<>(1000),
+            new ThreadFactoryBuilder().setNameFormat("FilterService-%d").build(),
+            new ThreadPoolExecutor.AbortPolicy());
+
+    public static ExecutorService defaultPool() {
+        return DEFAULT;
+    }
+
+    public static ExecutorService recallPool() {
+        return RECALL;
+    }
+
+    public static ExecutorService filterPool() {
+        return FILTER;
+    }
+
+
+}

+ 63 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/config/RedisTemplateConfig.java

@@ -0,0 +1,63 @@
+package com.tzld.longarticle.recommend.server.config;
+
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Configuration
+public class RedisTemplateConfig {
+
+    @Bean("redisPool")
+    @ConfigurationProperties(prefix = "spring.redis.lettuce.pool")
+    public GenericObjectPoolConfig<LettucePoolingClientConfiguration> redisPool() {
+        return new GenericObjectPoolConfig<>();
+    }
+
+    @Bean("redisConfig")
+    @ConfigurationProperties(prefix = "spring.redis")
+    public RedisStandaloneConfiguration tairConfig() {
+        return new RedisStandaloneConfiguration();
+    }
+
+    @Bean("redisFactory")
+    @Primary
+    public LettuceConnectionFactory factory(@Qualifier("redisPool") GenericObjectPoolConfig<LettucePoolingClientConfiguration> redisPool,
+                                            @Qualifier("redisConfig") RedisStandaloneConfiguration redisConfig) {
+        LettuceClientConfiguration lettuceClientConfiguration =
+                LettucePoolingClientConfiguration.builder().poolConfig(redisPool).build();
+        return new LettuceConnectionFactory(redisConfig, lettuceClientConfiguration);
+    }
+
+    @Bean(name = "redisTemplate")
+    public RedisTemplate<String, String> getRedisTemplate(@Qualifier("redisFactory") RedisConnectionFactory factory) {
+        return buildRedisTemplateByString(factory);
+    }
+
+    /**
+     * 构建redisTemplate 使用string序列化
+     *
+     * @param factory
+     * @return
+     */
+    public RedisTemplate<String, String> buildRedisTemplateByString(RedisConnectionFactory factory) {
+        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
+        redisTemplate.setConnectionFactory(factory);
+        // key的序列化类型 保证可读性
+        redisTemplate.setKeySerializer(new StringRedisSerializer());
+        redisTemplate.setValueSerializer(new StringRedisSerializer());
+        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
+        return redisTemplate;
+    }
+
+}

+ 17 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/Content.java

@@ -0,0 +1,17 @@
+package com.tzld.longarticle.recommend.server.model;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author dyp
+ */
+
+@NoArgsConstructor
+@Getter
+@Setter
+public class Content {
+
+}
+

+ 17 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/RecommendRequest.java

@@ -0,0 +1,17 @@
+package com.tzld.longarticle.recommend.server.model;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author dyp
+ */
+
+@NoArgsConstructor
+@Getter
+@Setter
+public class RecommendRequest {
+
+}
+

+ 17 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/model/RecommendResponse.java

@@ -0,0 +1,17 @@
+package com.tzld.longarticle.recommend.server.model;
+
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author dyp
+ */
+
+@NoArgsConstructor
+@Getter
+@Setter
+public class RecommendResponse {
+
+}
+

+ 28 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/AIGCRemoteService.java

@@ -0,0 +1,28 @@
+package com.tzld.longarticle.recommend.server.remote;
+
+import com.tzld.longarticle.recommend.server.common.HttpPoolFactory;
+import com.tzld.longarticle.recommend.server.model.Content;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+@Service
+@Slf4j
+public class AIGCRemoteService {
+    private final CloseableHttpClient client = HttpPoolFactory.defaultPool();
+    private String aigcGetAllContentUrl;
+
+
+    // TODO 如果过滤失败,那么认为所有视频都被过滤掉
+    public List<Content> getAllContent() {
+
+        return Collections.emptyList();
+    }
+
+}

+ 81 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/remote/NLPRemoteService.java

@@ -0,0 +1,81 @@
+package com.tzld.longarticle.recommend.server.remote;
+
+import com.google.common.reflect.TypeToken;
+import com.tzld.longarticle.recommend.server.common.HttpPoolFactory;
+import com.tzld.longarticle.recommend.server.util.JSONUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+
+/**
+ * @author dyp
+ */
+@Service
+@Slf4j
+public class NLPRemoteService {
+
+    private final CloseableHttpClient client = HttpPoolFactory.defaultPool();
+
+    private String nlpServerUrl;
+
+    // TODO 如果过滤失败,那么认为所有视频都被过滤掉
+    public List<Long> filterViewedVideo(int appType, String mid, String uid, List<Long> videoIds, String cityCode,
+                                        Set<String> abExpCodes, Long hotSceneType, String clientIp) {
+
+        CloseableHttpResponse chr = null;
+        try {
+            HttpPost post = new HttpPost(nlpServerUrl);
+            post.addHeader("Connection", "close");
+            post.addHeader("content-type", "application/json");
+            Map<String, Object> param = new HashMap<>();
+            param.put("appType", appType);
+            post.setEntity(new StringEntity(JSONUtils.toJson(param)));
+
+            chr = client.execute(post);
+            if (chr == null
+                    || chr.getStatusLine() == null
+                    || chr.getStatusLine().getStatusCode() != 200) {
+                log.error("filterViewedVideo failed http status exception!");
+                return Collections.emptyList();
+            }
+            HttpEntity entity = chr.getEntity();
+            if (entity == null) {
+                return Collections.emptyList();
+            }
+            String content = EntityUtils.toString(entity);
+            Map<String, String> data = JSONUtils.fromJson(content,
+                    new TypeToken<Map<String, String>>() {
+                    },
+                    Collections.emptyMap());
+            if (data.get("code") == null
+                    || !data.get("code").equals("0")) {
+                log.error("filterViewedVideo failed videoFilterUrl return code exception! data={}",
+                        JSONUtils.toJson(data));
+                return Collections.emptyList();
+            }
+            return JSONUtils.fromJson(data.get("data"),
+                    new TypeToken<List<Long>>() {
+                    }, Collections.emptyList());
+
+        } catch (Exception e) {
+            log.error("invoke http filterViewedVideo error", e);
+        } finally {
+            try {
+                if (chr != null) {
+                    chr.close();
+                }
+            } catch (Exception ex) {
+                log.error("close CloseableHttpResponse error", ex);
+            }
+        }
+        return Collections.emptyList();
+    }
+
+}

+ 22 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/RecommendParam.java

@@ -0,0 +1,22 @@
+package com.tzld.longarticle.recommend.server.service;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author dyp
+ */
+
+@NoArgsConstructor
+@Getter
+@Setter
+public class RecommendParam {
+
+}
+

+ 58 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/RecommendService.java

@@ -0,0 +1,58 @@
+package com.tzld.longarticle.recommend.server.service;
+
+import com.tzld.longarticle.recommend.server.model.RecommendRequest;
+import com.tzld.longarticle.recommend.server.model.RecommendResponse;
+import com.tzld.longarticle.recommend.server.service.rank.RankParam;
+import com.tzld.longarticle.recommend.server.service.rank.RankResult;
+import com.tzld.longarticle.recommend.server.service.rank.RankService;
+import com.tzld.longarticle.recommend.server.service.recall.RecallParam;
+import com.tzld.longarticle.recommend.server.service.recall.RecallResult;
+import com.tzld.longarticle.recommend.server.service.recall.RecallService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author dyp
+ */
+@Service
+@Slf4j
+public class RecommendService {
+
+
+    @Autowired
+    private RecallService recallService;
+    @Autowired
+    private RankService rankService;
+
+
+    public RecommendParam genRecommendParam(RecommendRequest request) {
+        RecommendParam param = new RecommendParam();
+        return param;
+    }
+
+    public RecommendResponse recommend(RecommendRequest request) {
+
+        RecommendParam param = genRecommendParam(request);
+        RecallResult recallResult = recallService.recall(convertToRecallParam(param));
+        RankResult rankResult = rankService.rank(convertToRankParam(param, recallResult));
+        // MergeResult mergeResult = mergeService.merge(convertToMergeParam(param, rankResult));
+
+        RecommendResponse response = new RecommendResponse();
+
+        return response;
+    }
+
+    public RecallParam convertToRecallParam(RecommendParam param) {
+        RecallParam recallParam = new RecallParam();
+        return recallParam;
+    }
+
+
+    public RankParam convertToRankParam(RecommendParam param, RecallResult recallResult) {
+        RankParam rankParam = new RankParam();
+        rankParam.setRecallResult(recallResult);
+        return rankParam;
+    }
+
+}

+ 23 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/ServiceBeanFactory.java

@@ -0,0 +1,23 @@
+package com.tzld.longarticle.recommend.server.service;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author dyp
+ */
+@Component
+public class ServiceBeanFactory implements ApplicationContextAware {
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        this.applicationContext = applicationContext;
+    }
+
+    public static <T> T getBean(Class<T> clazz) {
+        return applicationContext.getBean(clazz);
+    }
+}

+ 17 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/WarmUpService.java

@@ -0,0 +1,17 @@
+package com.tzld.longarticle.recommend.server.service;
+
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * @author dyp
+ */
+@Component
+@Order(1)
+public class WarmUpService {
+    @PostConstruct
+    public void warmup() {
+    }
+}

+ 41 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/FilterParam.java

@@ -0,0 +1,41 @@
+package com.tzld.longarticle.recommend.server.service.filter;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author dyp
+ */
+@Data
+public class FilterParam {
+    private List<Long> videoIds;
+    private Map<Long, String> flowPoolMap;
+    private int appType;
+    private String mid;
+    private String uid;
+
+    // 风险过滤
+    private Boolean riskFilterFlag;
+    private Map<Integer, List<String>> appRegionFiltered;
+    private List<Long> videosWithRisk;
+    private String regionCode;
+    private String cityCode;
+    private int forceTruncation;
+    private Set<String> abExpCodes;
+
+    public boolean concurrent; // hardcode 临时解决过滤慢的问题
+    public boolean notUsePreView;
+
+    // 层 - 实验
+    private Map<String, String> expIdMap;
+
+    private String abCode;
+
+    private Long hotSceneType;
+
+    private String clientIp;
+
+}

+ 17 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/FilterResult.java

@@ -0,0 +1,17 @@
+package com.tzld.longarticle.recommend.server.service.filter;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class FilterResult {
+    private List<Long> contentIds;
+}

+ 74 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/FilterService.java

@@ -0,0 +1,74 @@
+package com.tzld.longarticle.recommend.server.service.filter;
+
+import com.google.common.collect.Lists;
+import com.tzld.longarticle.recommend.server.common.ThreadPoolFactory;
+import com.tzld.longarticle.recommend.server.service.ServiceBeanFactory;
+import com.tzld.longarticle.recommend.server.service.filter.strategy.SimilarityStrategy;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Service
+public class FilterService {
+    private final ExecutorService pool = ThreadPoolFactory.filterPool();
+
+    public FilterResult filter(FilterParam param) {
+        List<Long> videoIds = viewFilter(param);
+
+        return new FilterResult(videoIds);
+    }
+
+    protected List<Long> viewFilter(FilterParam param) {
+
+        List<FilterStrategy> strategies = getStrategies(param);
+        CountDownLatch cdl = new CountDownLatch(strategies.size());
+        List<Future<List<Long>>> futures = new ArrayList<>();
+        for (final FilterStrategy strategy : strategies) {
+            Future<List<Long>> future = pool.submit(() -> {
+                List<Long> result = strategy.filter(param);
+                cdl.countDown();
+                return result;
+            });
+            futures.add(future);
+        }
+        try {
+            cdl.await(1000, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            log.error("filter error", e);
+            return null;
+        }
+
+        List<List<Long>> videoIds = new ArrayList<>();
+        for (Future<List<Long>> f : futures) {
+            try {
+                videoIds.add(f.get());
+            } catch (Exception e) {
+                log.error("future get error ", e);
+            }
+        }
+        if (CollectionUtils.isEmpty(videoIds)) {
+            return Collections.emptyList();
+        }
+        List<Long> result = Lists.newArrayList(param.getVideoIds());
+        for (int i = 0; i < videoIds.size(); ++i) {
+            result.retainAll(videoIds.get(i));
+        }
+        return result;
+    }
+
+    private List<FilterStrategy> getStrategies(FilterParam param) {
+        List<FilterStrategy> strategies = new ArrayList<>();
+        strategies.add(ServiceBeanFactory.getBean(SimilarityStrategy.class));
+
+        return strategies;
+    }
+}

+ 8 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/FilterStrategy.java

@@ -0,0 +1,8 @@
+package com.tzld.longarticle.recommend.server.service.filter;
+
+
+import java.util.List;
+
+public interface FilterStrategy {
+    List<Long> filter(FilterParam param);
+}

+ 22 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/filter/strategy/SimilarityStrategy.java

@@ -0,0 +1,22 @@
+package com.tzld.longarticle.recommend.server.service.filter.strategy;
+
+import com.tzld.longarticle.recommend.server.service.filter.FilterParam;
+import com.tzld.longarticle.recommend.server.service.filter.FilterStrategy;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+@Component
+@Slf4j
+public class SimilarityStrategy implements FilterStrategy {
+
+    @Override
+    public List<Long> filter(FilterParam param) {
+        return null;
+    }
+
+}

+ 72 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/odps/ODPSManager.java

@@ -0,0 +1,72 @@
+package com.tzld.longarticle.recommend.server.service.odps;
+
+import com.aliyun.odps.Instance;
+import com.aliyun.odps.Odps;
+import com.aliyun.odps.OdpsException;
+import com.aliyun.odps.account.Account;
+import com.aliyun.odps.account.AliyunAccount;
+import com.aliyun.odps.data.Record;
+import com.aliyun.odps.task.SQLTask;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+/**
+ * @author sunxy
+ */
+@Slf4j
+@Component
+public class ODPSManager {
+    private final static String ACCESSID = "LTAIWYUujJAm7CbH";
+    private final static String ACCESSKEY = "RfSjdiWwED1sGFlsjXv0DlfTnZTG1P";
+    private final static String ENDPOINT = "http://service.cn.maxcompute.aliyun.com/api";
+
+    public List<Record> query(String sql) {
+        Account account = new AliyunAccount(ACCESSID, ACCESSKEY);
+        Odps odps = new Odps(account);
+        odps.setEndpoint(ENDPOINT);
+        odps.setDefaultProject("loghubods");
+        Instance i;
+        try {
+            i = SQLTask.run(odps, sql);
+            i.waitForSuccess();
+            List<Record> records = SQLTask.getResultByInstanceTunnel(i);
+            if (Objects.nonNull(records) && records.size() != 0) {
+                return records;
+            }
+        } catch (Exception e) {
+            log.error("odps query error", e);
+        }
+        return Collections.emptyList();
+    }
+
+    public static void main(String[] args) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(new Date());
+        cal.add(Calendar.DATE, -1);
+        Date date2 = cal.getTime();
+        SimpleDateFormat format2 = new SimpleDateFormat("yyyyMMdd");
+
+        Account account = new AliyunAccount(ACCESSID, ACCESSKEY);
+        Odps odps = new Odps(account);
+        odps.setEndpoint(ENDPOINT);
+        odps.setDefaultProject("loghubods");
+        String sql = "select * from yesterday_return_top1000 where dt='" + format2.format(date2) + "';";
+        Instance i;
+        try {
+            i = SQLTask.run(odps, sql);
+            i.waitForSuccess();
+            List<Record> records = SQLTask.getResult(i);
+            for (Record r : records) {
+                System.out.println(Integer.parseInt(r.get(0).toString()));
+                System.out.println(r.get(1).toString());
+            }
+        } catch (OdpsException e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 14 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankParam.java

@@ -0,0 +1,14 @@
+package com.tzld.longarticle.recommend.server.service.rank;
+
+import com.tzld.longarticle.recommend.server.service.recall.RecallResult;
+import lombok.Data;
+
+/**
+ * @author dyp
+ */
+@Data
+public class RankParam {
+    private RecallResult recallResult;
+    private int size;
+
+}

+ 17 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankResult.java

@@ -0,0 +1,17 @@
+package com.tzld.longarticle.recommend.server.service.rank;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class RankResult {
+    private List<Content> contents;
+}

+ 135 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankRouter.java

@@ -0,0 +1,135 @@
+package com.tzld.longarticle.recommend.server.service.rank;
+
+import com.aliyun.odps.utils.StringUtils;
+import com.tzld.piaoquan.recommend.server.service.rank.strategy.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+@Slf4j
+public class RankRouter {
+    @Autowired
+    private RankService rankService;
+    @Autowired
+    private RankStrategy4Rankv2Model rankStrategy4Rankv2Model;
+    @Autowired
+    private RankStrategy4RankModel rankStrategy4RankModel;
+    @Autowired
+    private RankStrategy4Density rankStrategy4Density;
+    @Autowired
+    private RankStrategy4RegionMergeModelV536 rankStrategy4RegionMergeModelV536;
+    @Autowired
+    private RankStrategy4RegionMergeModelV551 rankStrategy4RegionMergeModelV3;
+    @Autowired
+    private RankStrategy4RegionMergeModelV546 rankStrategy4RegionMergeModelV546;
+    @Autowired
+    private RankStrategy4RegionMergeModelV547 rankStrategy4RegionMergeModelV547;
+    @Autowired
+    private RankStrategy4RegionMergeModelV548 rankStrategy4RegionMergeModelV548;
+    @Autowired
+    private RankStrategy4RegionMergeModelV551 rankStrategy4RegionMergeModelV551;
+    @Autowired
+    private RankStrategy4RegionMergeModelV552 rankStrategy4RegionMergeModelV552;
+    @Autowired
+    private RankStrategy4RegionMergeModelV553 rankStrategy4RegionMergeModelV553;
+    @Autowired
+    private RankStrategy4RegionMergeModelV561 rankStrategy4RegionMergeModelV561;
+    @Autowired
+    private RankStrategy4RegionMergeModelV562 rankStrategy4RegionMergeModelV562;
+    @Autowired
+    private RankStrategy4RegionMergeModelV563 rankStrategy4RegionMergeModelV563;
+    @Autowired
+    private RankStrategy4RegionMergeModelV564 rankStrategy4RegionMergeModelV564;
+    @Autowired
+    private RankStrategy4RegionMergeModelV565 rankStrategy4RegionMergeModelV565;
+    @Autowired
+    private RankStrategy4RegionMergeModelV566 rankStrategy4RegionMergeModelV566;
+    @Autowired
+    private RankStrategy4RegionMergeModelV567 rankStrategy4RegionMergeModelV567;
+    @Autowired
+    private RankStrategy4RegionMergeModelV999 rankStrategy4RegionMergeModelV999;
+    @Autowired
+    private RankStrategy4RegionMergeModelV569 rankStrategy4RegionMergeModelV569;
+    @Autowired
+    private RankStrategy4RegionMergeModelV650 rankStrategy4RegionMergeModelV650;
+    @Autowired
+    private RankStrategy4RegionMergeModelV654 rankStrategy4RegionMergeModelV654;
+    @Autowired
+    private RankStrategy4RegionMergeModelV655 rankStrategy4RegionMergeModelV655;
+    @Autowired
+    private FestivalStrategy4RankModel festivalStrategy4RankModel;
+
+    @Autowired
+    private RankStrategyFlowThompsonModel rankStrategyFlowThompsonModel;
+    @Autowired
+    private RankStrategy4RegionMerge rankStrategy4RegionMerge;
+    @Autowired
+    private RankStrategy4ShareDeepAndWidth rankStrategy4ShareDeepAndWidth;
+
+    public RankResult rank(RankParam param) {
+        String abCode = param.getAbCode();
+        if (StringUtils.isBlank(abCode)) {
+            return rankService.rank(param);
+        }
+        switch (abCode) {
+            case "60097":
+            case "60098": // 533
+            case "60111": // 561
+            case "60112": // 562
+                return rankStrategy4Density.rank(param);
+            case "60101":
+                return rankStrategy4RankModel.rank(param);
+            case "60113": // 563
+                return rankStrategy4RegionMergeModelV563.rank(param);
+            case "60114": // 564
+                return rankStrategy4RegionMergeModelV564.rank(param);
+            case "60115": // 565
+                return rankStrategy4RegionMergeModelV565.rank(param);
+            case "60116": // 566
+                return rankStrategy4RegionMergeModelV566.rank(param);
+            case "60117": // 567
+                return rankStrategy4RegionMergeModelV567.rank(param);
+            case "60118": // 568
+                return rankStrategy4RegionMergeModelV999.rank(param);
+            case "60119": // 569
+                return rankStrategy4RegionMergeModelV569.rank(param);
+            case "60120": // 576
+                return rankStrategy4RegionMerge.rank(param);
+            case "60121": // 536
+                return rankStrategy4RegionMergeModelV536.rank(param);
+            case "60122": // 537
+                return rankStrategy4RegionMergeModelV546.rank(param);
+            case "60123": // 541
+                return rankStrategy4RegionMergeModelV3.rank(param);
+            case "60124": // 546
+                return rankStrategy4RegionMergeModelV546.rank(param);
+            case "60125": // 547
+                return rankStrategy4RegionMergeModelV547.rank(param);
+            case "60126": // 548
+                return rankStrategy4RegionMergeModelV548.rank(param);
+            case "60105": // 551
+                return rankStrategy4RegionMergeModelV551.rank(param);
+            case "60106": // 552
+                return rankStrategy4RegionMergeModelV552.rank(param);
+            case "60107": // 553
+                return rankStrategy4RegionMergeModelV553.rank(param);
+            case "60130":
+            case "60131":
+            case "60132":
+                return festivalStrategy4RankModel.rank(param);
+            case "60150": // 645
+                return rankStrategy4ShareDeepAndWidth.rank(param);
+            case "60151": // 650
+                return rankStrategy4RegionMergeModelV650.rank(param);
+            case "60654": // 654
+                return rankStrategy4RegionMergeModelV654.rank(param);
+            case "60655": // 655
+                return rankStrategy4RegionMergeModelV655.rank(param);
+            default:
+                break;
+        }
+        return rankService.rank(param);
+    }
+}
+

+ 27 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/rank/RankService.java

@@ -0,0 +1,27 @@
+package com.tzld.longarticle.recommend.server.service.rank;
+
+
+import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+/**
+ * @author dyp
+ */
+@Service
+@Slf4j
+public class RankService {
+    @Value("${aaa:528}")
+    private String aaa;
+    @ApolloJsonValue("${bbb:{}}")
+    protected Map<String, String> bbb;
+
+    public RankResult rank(RankParam param) {
+        RankResult result = new RankResult();
+        return result;
+    }
+
+}

+ 16 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/FilterParamFactory.java

@@ -0,0 +1,16 @@
+package com.tzld.longarticle.recommend.server.service.recall;
+
+import com.tzld.longarticle.recommend.server.model.Content;
+import com.tzld.longarticle.recommend.server.service.filter.FilterParam;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+public class FilterParamFactory {
+    public static FilterParam create(RecallParam param, List<Content> contents) {
+        FilterParam filterParam = new FilterParam();
+        return filterParam;
+    }
+}

+ 11 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallParam.java

@@ -0,0 +1,11 @@
+package com.tzld.longarticle.recommend.server.service.recall;
+
+import lombok.Data;
+
+/**
+ * @author dyp
+ */
+@Data
+public class RecallParam {
+
+}

+ 27 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallResult.java

@@ -0,0 +1,27 @@
+package com.tzld.longarticle.recommend.server.service.recall;
+
+import com.tzld.longarticle.recommend.server.model.Content;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class RecallResult {
+    private List<RecallData> data;
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class RecallData {
+        private List<Content> contents;
+    }
+
+
+}

+ 86 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallService.java

@@ -0,0 +1,86 @@
+package com.tzld.longarticle.recommend.server.service.recall;
+
+import com.tzld.longarticle.recommend.server.common.ThreadPoolFactory;
+import com.tzld.longarticle.recommend.server.model.Content;
+import com.tzld.longarticle.recommend.server.service.recall.strategy.DefaultRecallStrategy;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author dyp
+ */
+@Service
+@Slf4j
+public class RecallService implements ApplicationContextAware {
+
+    private final Map<String, RecallStrategy> strategyMap = new HashMap<>();
+    private ApplicationContext applicationContext;
+    private final ExecutorService pool = ThreadPoolFactory.recallPool();
+
+    @PostConstruct
+    public void init() {
+        Map<String, RecallStrategy> type = applicationContext.getBeansOfType(RecallStrategy.class);
+        for (Map.Entry<String, RecallStrategy> entry : type.entrySet()) {
+            RecallStrategy value = entry.getValue();
+            strategyMap.put(value.getClass().getSimpleName(), value);
+        }
+    }
+
+    public RecallResult recall(RecallParam param) {
+        List<RecallStrategy> strategies = getRecallStrategy(param);
+        CountDownLatch cdl = new CountDownLatch(strategies.size());
+        List<Future<RecallResult.RecallData>> recallResultFutures = new ArrayList<>();
+        for (final RecallStrategy strategy : strategies) {
+            Future<RecallResult.RecallData> future = pool.submit(() -> {
+                List<Content> result = strategy.recall(param);
+                cdl.countDown();
+                return new RecallResult.RecallData(result);
+            });
+            recallResultFutures.add(future);
+        }
+        try {
+            cdl.await(3000, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            log.error("recall error", e);
+            return null;
+        }
+
+        List<RecallResult.RecallData> results = new ArrayList<>();
+        for (Future<RecallResult.RecallData> f : recallResultFutures) {
+            try {
+                RecallResult.RecallData data = f.get();
+                results.add(data);
+            } catch (Exception e) {
+                log.error("future get error ", e);
+            }
+        }
+
+        return new RecallResult(results);
+    }
+
+    private List<RecallStrategy> getRecallStrategy(RecallParam param) {
+        List<RecallStrategy> strategies = new ArrayList<>();
+        strategies.add(strategyMap.get(DefaultRecallStrategy.class.getSimpleName()));
+
+        return strategies;
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        this.applicationContext = applicationContext;
+    }
+
+}

+ 12 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/RecallStrategy.java

@@ -0,0 +1,12 @@
+package com.tzld.longarticle.recommend.server.service.recall;
+
+import com.tzld.longarticle.recommend.server.model.Content;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+public interface RecallStrategy {
+    List<Content> recall(RecallParam param);
+}

+ 38 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recall/strategy/DefaultRecallStrategy.java

@@ -0,0 +1,38 @@
+package com.tzld.longarticle.recommend.server.service.recall.strategy;
+
+import com.tzld.longarticle.recommend.server.model.Content;
+import com.tzld.longarticle.recommend.server.remote.AIGCRemoteService;
+import com.tzld.longarticle.recommend.server.service.filter.FilterParam;
+import com.tzld.longarticle.recommend.server.service.filter.FilterResult;
+import com.tzld.longarticle.recommend.server.service.filter.FilterService;
+import com.tzld.longarticle.recommend.server.service.recall.FilterParamFactory;
+import com.tzld.longarticle.recommend.server.service.recall.RecallParam;
+import com.tzld.longarticle.recommend.server.service.recall.RecallStrategy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author sunxy
+ */
+@Component
+public class DefaultRecallStrategy implements RecallStrategy {
+
+    @Autowired
+    private FilterService filterService;
+    @Autowired
+    private AIGCRemoteService aigcRemoteService;
+
+    @Override
+    public List<Content> recall(RecallParam param) {
+
+        List<Content> content = aigcRemoteService.getAllContent();
+        FilterParam filterParam = FilterParamFactory.create(param, content);
+        FilterResult filterResult = filterService.filter(filterParam);
+        List<Content> videosResult = new ArrayList<>();
+        return videosResult;
+    }
+
+}

+ 59 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/CommonCollectionUtils.java

@@ -0,0 +1,59 @@
+package com.tzld.longarticle.recommend.server.util;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * @author dyp
+ */
+public class CommonCollectionUtils {
+
+    public static <T> List<T> iterableToList(Iterable<T> iterable) {
+        List<T> list = new ArrayList<>();
+        for (T element : iterable) {
+            list.add(element);
+        }
+        return list;
+    }
+
+    public static <T, R> List<R> toList(List<T> list, Function<T, R> map) {
+        if (CollectionUtils.isEmpty(list)) {
+            return Collections.emptyList();
+        }
+        return list.stream().map(map).collect(Collectors.toList());
+    }
+
+    public static <T, R> List<R> toListDistinct(List<T> list, Function<T, R> map) {
+        if (CollectionUtils.isEmpty(list)) {
+            return Collections.emptyList();
+        }
+        return list.stream().map(map).distinct().collect(Collectors.toList());
+    }
+
+
+    public static <T, K, V> Map<K, V> toMap(Collection<T> col, Function<T, K> keyFunc, Function<T, V> valueFunc) {
+        if (CollectionUtils.isEmpty(col)) {
+            return Collections.emptyMap();
+        }
+        return col.stream().collect(Collectors.toMap(keyFunc::apply, valueFunc::apply, (u, v) -> v, HashMap::new));
+    }
+
+    public static <T, R> Set<R> toSet(Collection<T> col, Function<T, R> func) {
+        if (CollectionUtils.isEmpty(col)) {
+            return Collections.emptySet();
+        }
+        return col.stream()
+                .map(c -> func.apply(c))
+                .collect(Collectors.toSet());
+    }
+
+    public static <T> boolean contains(Collection<T> col, T ele) {
+        if (CollectionUtils.isEmpty(col)) {
+            return false;
+        }
+        return col.contains(ele);
+    }
+}

+ 65 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/DateUtils.java

@@ -0,0 +1,65 @@
+package com.tzld.longarticle.recommend.server.util;
+
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author dyp
+ */
+public final class DateUtils {
+    public static String getCurrentDateStr(String format) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
+        Date currentDate = new Date();
+        return dateFormat.format(currentDate);
+    }
+
+    public static int getCurrentHour() {
+        Calendar calendar = Calendar.getInstance();
+        return calendar.get(Calendar.HOUR_OF_DAY);
+    }
+
+    public static String getBeforeDaysDateStr(String format, int d) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(new Date());
+        calendar.add(Calendar.DAY_OF_MONTH, -d);
+        Date previousDate = calendar.getTime();
+        return dateFormat.format(previousDate);
+    }
+
+
+    public static boolean ifTimeRangeInNow(String timeRange) {
+        try {
+
+            String[] split = timeRange.split("-");
+            if (split.length != 2) {
+                return false;
+            }
+            String startTime = split[0];
+            String endTime = split[1];
+            if (startTime.length() != 10 || endTime.length() != 10) {
+                return false;
+            }
+            LocalDateTime now = LocalDateTime.now();
+            LocalDateTime start = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyyMMddHH"));
+            LocalDateTime end = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyyMMddHH"));
+            return now.equals(start) || (now.isAfter(start) && now.isBefore(end));
+        } catch (Exception e) {
+//            e.printStackTrace();
+            return false;
+        }
+    }
+
+
+    public static void main(String[] args) {
+        Calendar calendar = Calendar.getInstance();
+
+        System.out.println((calendar.get(Calendar.DAY_OF_WEEK) + 6) % 7);
+        System.out.println(new SimpleDateFormat("yyyyMMdd").format(calendar.getTime()));
+        System.out.println(new SimpleDateFormat("HH").format(calendar.getTime()));
+
+    }
+}

+ 96 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/HttpClientFactory.java

@@ -0,0 +1,96 @@
+package com.tzld.longarticle.recommend.server.util;
+
+import com.google.common.collect.Lists;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.ssl.SSLContexts;
+import org.slf4j.MDC;
+
+import javax.net.ssl.SSLContext;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+public class HttpClientFactory {
+
+    private static final ScheduledExecutorService SCHEDULED_CLOSED_EXECUTOR = new ScheduledThreadPoolExecutor(1,
+            new BasicThreadFactory.Builder().namingPattern("http conn-closed-thread-%s").priority(Thread.NORM_PRIORITY).daemon(false).build(), (r, e) -> log.error(" monitor push reject task error={}", e.toString()));
+
+    private static final List<HttpClientConnectionManager> HTTP_CLIENT_CONNECTION_MANAGERS = Lists.newArrayList();
+
+    static {
+        SCHEDULED_CLOSED_EXECUTOR.schedule(() -> HTTP_CLIENT_CONNECTION_MANAGERS.forEach(HttpClientConnectionManager::closeExpiredConnections), 5, TimeUnit.SECONDS);
+    }
+
+    private static HttpRequestInterceptor getInterceptor() {
+        HttpRequestInterceptor requestInterceptor = (request, context) -> {
+            try {
+                String missSpanId = MDC.get("missSpanId");
+                String missTraceId = MDC.get("request-id");
+                if (missTraceId != null && !"".equals(missTraceId.trim())) {
+                    request.setHeader("request-id", missTraceId);
+                }
+                if (missSpanId != null && !"".equals(missSpanId.trim())) {
+                    request.setHeader("missSpanId", missSpanId);
+                }
+            } catch (Exception e) {
+                log.error(e.getMessage(), e);
+            }
+        };
+        return requestInterceptor;
+    }
+
+    /**
+     * @param connectTimeout 连接超时时间 ms
+     * @param socketTimeout  读超时时间(等待数据超时时间)ms
+     * @param maxPerRoute    每个路由的最大连接数
+     * @param maxTotal       最大连接数
+     * @param retryCount     重试次数
+     * @return httpclient instance
+     */
+    public static CloseableHttpClient create(int connectTimeout, int socketTimeout, int maxPerRoute, int maxTotal,
+                                                int retryCount, int connectionWaitTimeout) {
+        try {
+            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout).setConnectionRequestTimeout(connectionWaitTimeout).build();
+            CloseableHttpClient client = HttpClientBuilder.create()
+                    .setDefaultRequestConfig(requestConfig)
+                    .setConnectionManager(createConnectionManager(maxPerRoute, maxTotal))
+                    .setRetryHandler(new DefaultHttpRequestRetryHandler(retryCount, false)).addInterceptorFirst(getInterceptor()).build();
+            return client;
+        } catch (Throwable e) {
+            log.error("create HttpPoolClient exception", e);
+            throw new RuntimeException("create HttpPoolClient exception");
+        }
+    }
+
+    private static PoolingHttpClientConnectionManager createConnectionManager(int maxPerRoute, int maxTotal) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
+        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial((chain, authType) -> true).build();
+        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
+                .register("http", PlainConnectionSocketFactory.getSocketFactory())
+                .register("https", new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE)).build();
+        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
+        cm.setDefaultMaxPerRoute(maxPerRoute);
+        cm.setMaxTotal(maxTotal);
+        HTTP_CLIENT_CONNECTION_MANAGERS.add(cm);
+        return cm;
+    }
+
+}

+ 49 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/JSONUtils.java

@@ -0,0 +1,49 @@
+package com.tzld.longarticle.recommend.server.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+@Slf4j
+public class JSONUtils {
+
+
+    public static String toJsonNew(Object obj) {
+        if (obj == null) {
+            return "";
+        }
+        try {
+            return JSONObject.toJSONString(obj);
+        } catch (Exception e) {
+            log.error("toJson exception", e);
+            return "";
+        }
+    }
+    public static String toJson(Object obj) {
+        if (obj == null) {
+            return "";
+        }
+        try {
+            return new Gson().toJson(obj);
+        } catch (Exception e) {
+            log.error("toJson exception", e);
+            return "";
+        }
+    }
+
+    public static <T> T fromJson(String value, TypeToken<T> typeToken, T defaultValue) {
+
+        if (StringUtils.isBlank(value)) {
+            return defaultValue;
+        }
+        try {
+            return JSONObject.parseObject(value, typeToken.getType());
+        } catch (Exception e) {
+            log.error("parseObject error! value=[{}]", value, e);
+        }
+        return defaultValue;
+    }
+
+}

+ 52 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/util/TraceUtils.java

@@ -0,0 +1,52 @@
+package com.tzld.longarticle.recommend.server.util;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.MDC;
+
+import java.net.InetAddress;
+
+/**
+ * @author dyp
+ */
+public class TraceUtils {
+    public static final String TRACE_ID_KEY = "traceId";
+    public static final String DEFAULT_TRACE_ID = "default_trace_id";
+
+    public static void setMDC() {
+        MDC.put(TraceUtils.TRACE_ID_KEY, genTraceId());
+    }
+
+    public static String currentTraceId() {
+        return MDC.get(TraceUtils.TRACE_ID_KEY);
+    }
+
+    public static void removeMDC() {
+        MDC.remove(TraceUtils.TRACE_ID_KEY);
+    }
+
+    public static String genTraceId() {
+        StringBuilder traceIdBuilder = new StringBuilder();
+        InetAddress address = InetAddress.getLoopbackAddress();
+        if (address == null) {
+            return DEFAULT_TRACE_ID;
+        }
+        String addressStr = address.getHostAddress();
+        if (StringUtils.isBlank(addressStr)) {
+            return DEFAULT_TRACE_ID;
+        }
+        String[] addressArr = addressStr.split("\\.");
+        if (addressArr.length != 4) {
+            return DEFAULT_TRACE_ID;
+        }
+
+        traceIdBuilder.append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addressArr[0])), 2, '0'))
+                .append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addressArr[1])), 2, '0'))
+                .append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addressArr[2])), 2, '0'))
+                .append(StringUtils.leftPad(Integer.toHexString(Integer.valueOf(addressArr[3])), 2, '0'))
+                .append(System.currentTimeMillis())
+                .append(RandomStringUtils.randomAlphabetic(4))
+                .append(Thread.currentThread().getId());
+        return traceIdBuilder.toString();
+    }
+}

+ 42 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/ControllerAspect.java

@@ -0,0 +1,42 @@
+package com.tzld.longarticle.recommend.server.web;
+
+import com.google.common.base.Stopwatch;
+import com.tzld.longarticle.recommend.server.util.JSONUtils;
+import com.tzld.longarticle.recommend.server.util.TraceUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author dyp
+ */
+@Aspect
+@Component
+@Slf4j
+public class ControllerAspect {
+
+    @Around("execution(* com.tzld.longarticle.recommend.server.web.*Controller.*(..))")
+    public Object around(ProceedingJoinPoint pjp) throws Throwable {
+        TraceUtils.setMDC();
+
+        String className = pjp.getTarget().getClass().getSimpleName();
+        MethodSignature signature = (MethodSignature) pjp.getSignature();
+        Stopwatch stopwatch = Stopwatch.createStarted();
+        log.info("request className=[{}], method=[{}], param=[{}]", className, signature.getName(),
+                JSONUtils.toJson(pjp.getArgs()));
+        Object result = pjp.proceed();
+        if (result != null && result instanceof String) {
+            log.info("response result=[{}] cost=[{}]", result, stopwatch.stop().elapsed(TimeUnit.MILLISECONDS));
+        } else {
+            log.info("response result=[{}] cost=[{}]", JSONUtils.toJson(result), stopwatch.stop().elapsed(TimeUnit.MILLISECONDS));
+        }
+
+        TraceUtils.removeMDC();
+        return result;
+    }
+}

+ 24 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/GlobalExceptionHandler.java

@@ -0,0 +1,24 @@
+package com.tzld.longarticle.recommend.server.web;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+
+@ControllerAdvice
+@Slf4j
+public class GlobalExceptionHandler {
+
+    @ExceptionHandler
+    @ResponseBody
+    public String handleException(HttpServletRequest hsr, Exception e) {
+        if (e instanceof RuntimeException) {
+            log.error("request uri {} error:{}", hsr.getRequestURI(), ExceptionUtils.getFullStackTrace(e));
+        }
+        return "";
+    }
+
+}

+ 18 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/HealthCheckController.java

@@ -0,0 +1,18 @@
+package com.tzld.longarticle.recommend.server.web;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author dyp
+ */
+@RestController
+@Slf4j
+public class HealthCheckController {
+
+    @GetMapping("/ok")
+    public String ok() {
+        return "ok";
+    }
+}

+ 29 - 0
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/web/RecommendV2Controller.java

@@ -0,0 +1,29 @@
+package com.tzld.longarticle.recommend.server.web;
+
+import com.tzld.longarticle.recommend.server.model.RecommendRequest;
+import com.tzld.longarticle.recommend.server.model.RecommendResponse;
+import com.tzld.longarticle.recommend.server.service.RecommendService;
+import com.tzld.longarticle.recommend.server.util.JSONUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author dyp
+ */
+@RestController
+@Slf4j
+public class RecommendV2Controller {
+    @Autowired
+    private RecommendService recommendService;
+
+    @RequestMapping("/homepage/recommend/v2")
+    public String homepageRecommend(@RequestBody RecommendRequest httpRequest) {
+        RecommendResponse response = recommendService.recommend(httpRequest);
+
+        return JSONUtils.toJson(response);
+    }
+
+}

+ 136 - 0
long-article-recommend-service/src/main/resources/application-dev.yml

@@ -0,0 +1,136 @@
+server:
+  port: 8001
+
+eureka:
+  instance:
+    prefer-ip-address: true #是否优先使用IP地址作为主机名的标识,默认false
+    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} #注册到eureka上的唯一实例ID
+    lease-renewal-interval-in-seconds: 10 #表示eureka client发送心跳给server端的频率,默认30
+    lease-expiration-duration-in-seconds: 30 #表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance,默认90
+  client:
+    registry-fetch-interval-seconds: 5  #定时从Eureka Server拉取服务注册信息的间隔时间
+    serviceUrl:
+      defaultZone: http://deveureka-internal.piaoquantv.com/eureka/
+
+spring:
+  redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  feature-redis:
+    hostName: r-bp1pi8wyv6lzvgjy5z.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  long-video-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  filter-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  video-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  data:
+    mongodb:
+      clusterHost: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com
+      clusterPort: 3717
+      secondaryHost: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com
+      secondaryPort: 3717
+      database: longvideo
+      username: lv
+      password: lv@2018
+      replicaSetName: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com:3717,dds-bp1de4fc73029b242144.mongodb.rds.aliyuncs.com:3717
+      # 连接池
+      maxConnectionIdleTime: 180000
+      # maxConnectionLifeTime: 30000
+      maxWaitTime: 3000
+      minSize: 5
+      maxSize: 10
+  datasource:
+    url: jdbc:mysql://rm-bp1k5853td1r25g3n690.mysql.rds.aliyuncs.com:3306/longvideo?useSSL=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
+    username: wx2016_longvideo
+    password: wx2016_longvideoP@assword1234
+    driver-class-name: com.mysql.jdbc.Driver
+    hikari:
+      connection-timeout: 30000
+      minimum-idle: 5
+      maximum-pool-size: 10
+      auto-commit: true
+      idle-timeout: 30000
+  jpa:
+    hibernate:
+      ddl-auto: validate
+    database: mysql
+xxl:
+  job:
+    admin:
+      addresses: http://xxl-job-test-internal.piaoquantv.com/xxl-job-admin
+    accessToken:
+    executor:
+      appname: ${spring.application.name}
+      address:
+      ip:
+      port: 9999
+      logpath: /datalog/weblog/${spring.application.name}/xxl-job/
+      logretentiondays: 30
+
+apollo:
+  meta: http://devapolloconfig-internal.piaoquantv.com
+
+aliyun:
+  log:
+    endpoint: cn-hangzhou.log.aliyuncs.com
+    accessKeyId: LTAIP6x1l3DXfSxm
+    accessKeySecret: KbTaM9ars4OX3PMS6Xm7rtxGr1FLon
+    project: recommend-server-test
+  timer:
+    log:
+      project: recommend-server-test
+      logStore: timer
+  blacklist:
+    filter:
+      log:
+        project: wqsd-video-test
+        store: video_blacklist_security_filter_log
+
+logging:
+  file:
+    path: ./${spring.application.name}/logs/

+ 131 - 0
long-article-recommend-service/src/main/resources/application-pre.yml

@@ -0,0 +1,131 @@
+server:
+  port: 8080
+
+eureka:
+  instance:
+    prefer-ip-address: true #是否优先使用IP地址作为主机名的标识,默认false
+    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} #注册到eureka上的唯一实例ID
+    lease-renewal-interval-in-seconds: 10 #表示eureka client发送心跳给server端的频率,默认30
+    lease-expiration-duration-in-seconds: 30 #表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance,默认90
+  client:
+    registry-fetch-interval-seconds: 5  #定时从Eureka Server拉取服务注册信息的间隔时间
+    serviceUrl:
+      defaultZone: http://preeureka-internal.piaoquantv.com/eureka/
+
+spring:
+  redis:
+    hostName: r-bp1fogs2mflr1ybfot.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  feature-redis:
+    hostName: r-bp1pi8wyv6lzvgjy5z.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  long-video-redis:
+    hostName: r-bp1oyhyx4mxgs6klyt561.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  filter-redis:
+    hostName: r-bp109v1gjl63qi00cb.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  video-redis:
+    hostName: r-bp1f3341ec15a634301.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  data:
+    mongodb:
+      clusterHost: s-bp14ce206f81b754.mongodb.rds.aliyuncs.com
+      clusterPort: 3717
+      secondaryHost: s-bp137073555e7bc4.mongodb.rds.aliyuncs.com
+      secondaryPort: 3717
+      database: longvideo
+      username: lv
+      password: lv2018
+      # 连接池
+      maxConnectionIdleTime: 180000
+      # maxConnectionLifeTime: 30000
+      maxWaitTime: 5000
+      minSize: 5
+      maxSize: 100
+  datasource:
+    url: jdbc:mysql://rm-bp1jjv3jv98133plv285-vpc-rw.mysql.rds.aliyuncs.com:3306/longvideo?useSSL=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
+    username: wx2016_longvideo
+    password: wx2016_longvideoP@assword1234
+    driver-class-name: com.mysql.jdbc.Driver
+    hikari:
+      connection-timeout: 30000
+      minimum-idle: 5
+      maximum-pool-size: 10
+      auto-commit: true
+      idle-timeout: 30000
+  jpa:
+    hibernate:
+      ddl-auto: validate
+    database: mysql
+xxl:
+  job:
+    admin:
+      addresses: http://xxl-job-pre-internal.piaoquantv.com/xxl-job-admin
+    accessToken:
+    executor:
+      appname: ${spring.application.name}
+      address:
+      ip:
+      port: 9999
+      logpath: /datalog/weblog/${spring.application.name}/xxl-job/
+      logretentiondays: 30
+
+apollo:
+  meta: http://preapolloconfig-internal.piaoquantv.com
+
+aliyun:
+  log:
+    endpoint: cn-hangzhou-intranet.log.aliyuncs.com
+    accessKeyId: LTAIP6x1l3DXfSxm
+    accessKeySecret: KbTaM9ars4OX3PMS6Xm7rtxGr1FLon
+    project: recommend-server
+  timer:
+    log:
+      project: recommend-server
+      logStore: timer
+  blacklist:
+    filter:
+      log:
+        project: wqsd-video
+        store: video_blacklist_security_filter_log

+ 131 - 0
long-article-recommend-service/src/main/resources/application-prod.yml

@@ -0,0 +1,131 @@
+server:
+  port: 8080
+
+eureka:
+  instance:
+    prefer-ip-address: true #是否优先使用IP地址作为主机名的标识,默认false
+    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} #注册到eureka上的唯一实例ID
+    lease-renewal-interval-in-seconds: 10 #表示eureka client发送心跳给server端的频率,默认30
+    lease-expiration-duration-in-seconds: 30 #表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance,默认90
+  client:
+    registry-fetch-interval-seconds: 5  #定时从Eureka Server拉取服务注册信息的间隔时间
+    serviceUrl:
+      defaultZone: http://eureka-internal.piaoquantv.com/eureka/
+
+spring:
+  redis:
+    hostName: r-bp1fogs2mflr1ybfot.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  feature-redis:
+    hostName: r-bp1pi8wyv6lzvgjy5z.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  long-video-redis:
+    hostName: r-bp1oyhyx4mxgs6klyt561.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  filter-redis:
+    hostName: r-bp109v1gjl63qi00cb.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  video-redis:
+    hostName: r-bp1f3341ec15a634301.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  data:
+    mongodb:
+      clusterHost: s-bp14ce206f81b754.mongodb.rds.aliyuncs.com
+      clusterPort: 3717
+      secondaryHost: s-bp137073555e7bc4.mongodb.rds.aliyuncs.com
+      secondaryPort: 3717
+      database: longvideo
+      username: lv
+      password: lv2018
+      # 连接池
+      maxConnectionIdleTime: 180000
+      # maxConnectionLifeTime: 30000
+      maxWaitTime: 5000
+      minSize: 5
+      maxSize: 100
+  datasource:
+    url: jdbc:mysql://rm-bp1jjv3jv98133plv285-vpc-rw.mysql.rds.aliyuncs.com:3306/longvideo?useSSL=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
+    username: wx2016_longvideo
+    password: wx2016_longvideoP@assword1234
+    driver-class-name: com.mysql.jdbc.Driver
+    hikari:
+      connection-timeout: 30000
+      minimum-idle: 5
+      maximum-pool-size: 100
+      auto-commit: true
+      idle-timeout: 30000
+  jpa:
+    hibernate:
+      ddl-auto: validate
+    database: mysql
+xxl:
+  job:
+    admin:
+      addresses: http://192.168.201.25:8182/xxl-job-admin
+    accessToken:
+    executor:
+      appname: ${spring.application.name}
+      address:
+      ip:
+      port: 9999
+      logpath: /datalog/weblog/${spring.application.name}/xxl-job/
+      logretentiondays: 30
+
+apollo:
+  meta: http://apolloconfig-internal.piaoquantv.com
+
+aliyun:
+  log:
+    endpoint: cn-hangzhou-intranet.log.aliyuncs.com
+    accessKeyId: LTAIP6x1l3DXfSxm
+    accessKeySecret: KbTaM9ars4OX3PMS6Xm7rtxGr1FLon
+    project: recommend-server
+  timer:
+    log:
+      project: recommend-server
+      logStore: timer
+  blacklist:
+    filter:
+      log:
+        project: wqsd-video
+        store: video_blacklist_security_filter_log

+ 132 - 0
long-article-recommend-service/src/main/resources/application-test.yml

@@ -0,0 +1,132 @@
+server:
+  port: 8080
+
+eureka:
+  instance:
+    prefer-ip-address: true #是否优先使用IP地址作为主机名的标识,默认false
+    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} #注册到eureka上的唯一实例ID
+    lease-renewal-interval-in-seconds: 10 #表示eureka client发送心跳给server端的频率,默认30
+    lease-expiration-duration-in-seconds: 30 #表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance,默认90
+  client:
+    registry-fetch-interval-seconds: 5  #定时从Eureka Server拉取服务注册信息的间隔时间
+    serviceUrl:
+      defaultZone: http://testeureka-internal.piaoquantv.com/eureka/
+
+spring:
+  redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  feature-redis:
+    hostName: r-bp1pi8wyv6lzvgjy5z.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  long-video-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  filter-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  video-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  data:
+    mongodb:
+      clusterHost: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com
+      clusterPort: 3717
+      secondaryHost: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com
+      secondaryPort: 3717
+      database: longvideo
+      username: lv
+      password: lv@2018
+      replicaSetName: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com:3717,dds-bp1de4fc73029b242144.mongodb.rds.aliyuncs.com:3717
+      # 连接池
+      maxConnectionIdleTime: 180000
+      # maxConnectionLifeTime: 30000
+      maxWaitTime: 3000
+      minSize: 5
+      maxSize: 10
+  datasource:
+    url: jdbc:mysql://rm-bp1k5853td1r25g3n690.mysql.rds.aliyuncs.com:3306/longvideo?useSSL=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
+    username: wx2016_longvideo
+    password: wx2016_longvideoP@assword1234
+    driver-class-name: com.mysql.jdbc.Driver
+    hikari:
+      connection-timeout: 30000
+      minimum-idle: 5
+      maximum-pool-size: 10
+      auto-commit: true
+      idle-timeout: 30000
+  jpa:
+    hibernate:
+      ddl-auto: validate
+    database: mysql
+xxl:
+  job:
+    admin:
+      addresses: http://xxl-job-test-internal.piaoquantv.com/xxl-job-admin
+    accessToken:
+    executor:
+      appname: ${spring.application.name}
+      address:
+      ip:
+      port: 9999
+      logpath: /datalog/weblog/${spring.application.name}/xxl-job/
+      logretentiondays: 30
+
+apollo:
+  meta: http://testapolloconfig-internal.piaoquantv.com
+
+aliyun:
+  log:
+    endpoint: cn-hangzhou-intranet.log.aliyuncs.com
+    accessKeyId: LTAIP6x1l3DXfSxm
+    accessKeySecret: KbTaM9ars4OX3PMS6Xm7rtxGr1FLon
+    project: recommend-server-test
+  timer:
+    log:
+      project: recommend-server-test
+      logStore: timer
+  blacklist:
+    filter:
+      log:
+        project: wqsd-video-test
+        store: video_blacklist_security_filter_log

+ 61 - 0
long-article-recommend-service/src/main/resources/application.yml

@@ -0,0 +1,61 @@
+spring:
+  profiles:
+    active: dev
+  application:
+    name: recommend-server
+#  cloud:
+#    sentinel:
+#      eager: true
+#      transport:
+#        port: 8719
+#      log:
+#        dir: /datalog/sentinel
+#      datasource:
+#        ds1:
+#          apollo:
+#            namespace-name: application
+#            flow-rules-key: sentinel.flowRules
+#            default-flow-rule-value: []
+#            rule-type: flow
+grpc:
+  server:
+    port: 9001
+    reflection-service-enabled: true
+  client:
+    recommend-feature:
+      negotiationType: PLAINTEXT
+    abtest:
+      negotiationType: PLAINTEXT
+
+server:
+  tomcat:
+    threads:
+      max: 1000
+    uri-encoding: UTF-8
+    accept-count: 1000
+    connection-timeout: 30000
+  servlet:
+    context-path: /recommend-server
+    session:
+      timeout: 60
+pagehelper:
+  helper-dialect: mysql
+
+logging:
+  file:
+    path: /datalog/weblog/${spring.application.name}/
+
+app:
+  id: recommend-server
+apollo:
+  bootstrap:
+    enabled: true
+    namespaces: application,RD.Experiment
+  cacheDir: /datalog/apollo-cache-dir
+
+feign:
+  client:
+    config:
+      default:
+        connectTimeout: 2000
+        readTimeout: 10000

+ 328 - 0
long-article-recommend-service/src/main/resources/logback.xml

@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
+<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
+<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
+<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
+<configuration scan="true" scanPeriod="10 seconds">
+
+    <!--为了防止进程退出时,内存中的数据丢失,请加上此选项-->
+    <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
+
+    <!-- 日志上下文名称 -->
+    <contextName>logback</contextName>
+
+    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
+    <!-- 日志输出格式 -->
+    <property name="LOG_PATTERN"
+              value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}\\(%L\\) - %msg%n"/>
+    <property name="mdcFields" value="traceId,appType"></property>
+
+    <!-- spring property使用方式 -->
+    <springProperty name="LOG_PATH" source="logging.file.path"/>
+    <springProperty name="aliyun_log_endpoint" source="aliyun.log.endpoint"/>
+    <springProperty name="aliyun_log_accessKeyId" source="aliyun.log.accessKeyId"/>
+    <springProperty name="aliyun_log_accessKeySecret" source="aliyun.log.accessKeySecret"/>
+    <springProperty name="aliyun_log_project" source="aliyun.log.project"/>
+
+    <!-- 彩色日志 -->
+    <!-- 彩色日志依赖的渲染类 -->
+    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
+    <conversionRule conversionWord="wex"
+                    converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
+    <conversionRule conversionWord="wEx"
+                    converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
+    <!-- 彩色日志格式 -->
+    <property name="CONSOLE_LOG_PATTERN"
+              value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}\\(%L\\)){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
+
+    <!--输出到控制台-->
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>info</level>
+        </filter>
+        <encoder>
+            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
+            <!-- 设置字符集 -->
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+
+    <!--输出到文件-->
+    <!-- 时间滚动输出 level为 DEBUG 日志 -->
+    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/debug.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>${LOG_PATTERN}</pattern>
+            <charset>UTF-8</charset> <!-- 设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志归档 -->
+            <fileNamePattern>${LOG_PATH}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>15</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录debug级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>debug</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 时间滚动输出 level为 INFO 日志 -->
+    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/info.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>${LOG_PATTERN}</pattern>
+            <charset>UTF-8</charset>
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 每天日志归档路径以及格式 -->
+            <fileNamePattern>${LOG_PATH}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>15</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录info级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>info</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 时间滚动输出 level为 WARN 日志 -->
+    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/warn.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>${LOG_PATTERN}</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_PATH}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>15</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录warn级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>warn</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 时间滚动输出 level为 ERROR 日志 -->
+    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/error.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>${LOG_PATTERN}</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_PATH}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>15</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录ERROR级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>ERROR</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <appender name="loghubAppenderInfo" class="com.tzld.piaoquan.recommend.server.common.RecommendLoghubAppender">
+        <!--必选项-->
+        <!-- 账号及网络配置 -->
+        <endpoint>${aliyun_log_endpoint}</endpoint>
+        <accessKeyId>${aliyun_log_accessKeyId}</accessKeyId>
+        <accessKeySecret>${aliyun_log_accessKeySecret}</accessKeySecret>
+        <!-- sls 项目配置 -->
+        <project>${aliyun_log_project}</project>
+        <logStore>info-log</logStore>
+        <!--必选项 (end)-->
+        <!-- 可选项 -->
+        <topic></topic>
+        <source></source>
+        <!-- 可选项 详见 '参数说明'-->
+        <totalSizeInBytes>104857600</totalSizeInBytes>
+        <maxBlockMs>0</maxBlockMs>
+        <ioThreadCount>16</ioThreadCount>
+        <batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
+        <batchCountThreshold>4096</batchCountThreshold>
+        <lingerMs>2000</lingerMs>
+        <retries>10</retries>
+        <baseRetryBackoffMs>100</baseRetryBackoffMs>
+        <maxRetryBackoffMs>50000</maxRetryBackoffMs>
+        <!-- 可选项 通过配置 encoder 的 pattern 自定义 log 的格式 -->
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>${LOG_PATTERN}</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>INFO</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <mdcFields>
+            ${mdcFields}
+        </mdcFields>
+    </appender>
+
+    <appender name="loghubAppenderWarn" class="com.tzld.piaoquan.recommend.server.common.RecommendLoghubAppender">
+        <!--必选项-->
+        <!-- 账号及网络配置 -->
+        <endpoint>${aliyun_log_endpoint}</endpoint>
+        <accessKeyId>${aliyun_log_accessKeyId}</accessKeyId>
+        <accessKeySecret>${aliyun_log_accessKeySecret}</accessKeySecret>
+        <!-- sls 项目配置 -->
+        <project>${aliyun_log_project}</project>
+        <logStore>warn-log</logStore>
+        <!--必选项 (end)-->
+        <!-- 可选项 -->
+        <topic></topic>
+        <source></source>
+        <!-- 可选项 详见 '参数说明'-->
+        <totalSizeInBytes>104857600</totalSizeInBytes>
+        <maxBlockMs>0</maxBlockMs>
+        <ioThreadCount>16</ioThreadCount>
+        <batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
+        <batchCountThreshold>4096</batchCountThreshold>
+        <lingerMs>2000</lingerMs>
+        <retries>10</retries>
+        <baseRetryBackoffMs>100</baseRetryBackoffMs>
+        <maxRetryBackoffMs>50000</maxRetryBackoffMs>
+        <!-- 可选项 通过配置 encoder 的 pattern 自定义 log 的格式 -->
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>${LOG_PATTERN}</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>WARN</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <mdcFields>
+            ${mdcFields}
+        </mdcFields>
+    </appender>
+
+    <appender name="loghubAppenderError" class="com.tzld.piaoquan.recommend.server.common.RecommendLoghubAppender">
+        <!--必选项-->
+        <!-- 账号及网络配置 -->
+        <endpoint>${aliyun_log_endpoint}</endpoint>
+        <accessKeyId>${aliyun_log_accessKeyId}</accessKeyId>
+        <accessKeySecret>${aliyun_log_accessKeySecret}</accessKeySecret>
+        <!-- sls 项目配置 -->
+        <project>${aliyun_log_project}</project>
+        <logStore>error-log</logStore>
+        <!--必选项 (end)-->
+        <!-- 可选项 -->
+        <topic></topic>
+        <source></source>
+        <!-- 可选项 详见 '参数说明'-->
+        <totalSizeInBytes>104857600</totalSizeInBytes>
+        <maxBlockMs>0</maxBlockMs>
+        <ioThreadCount>16</ioThreadCount>
+        <batchSizeThresholdInBytes>524288</batchSizeThresholdInBytes>
+        <batchCountThreshold>4096</batchCountThreshold>
+        <lingerMs>2000</lingerMs>
+        <retries>10</retries>
+        <baseRetryBackoffMs>100</baseRetryBackoffMs>
+        <maxRetryBackoffMs>50000</maxRetryBackoffMs>
+        <!-- 可选项 通过配置 encoder 的 pattern 自定义 log 的格式 -->
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>${LOG_PATTERN}</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>ERROR</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+        <mdcFields>
+            ${mdcFields}
+        </mdcFields>
+    </appender>
+
+    <!--
+        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、
+        以及指定<appender>。<logger>仅有一个name属性,
+        一个可选的level和一个可选的addtivity属性。
+        name:用来指定受此logger约束的某一个包或者具体的某一个类。
+        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
+              还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
+              如果未设置此属性,那么当前logger将会继承上级的级别。
+        addtivity:是否向上级logger传递打印信息。默认是true。
+    -->
+    <!--<logger name="org.springframework.web" level="info"/>-->
+    <!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
+    <!--
+        使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
+        第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
+        第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
+     -->
+
+    <!--
+        root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
+        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
+        不能设置为INHERITED或者同义词NULL。默认是DEBUG
+        可以包含零个或多个元素,标识这个appender将会添加到这个logger。
+    -->
+
+    <springProfile name="dev">
+        <logger name="com.tzld.piaoquan.recommend.server" level="info"/>
+    </springProfile>
+    <springProfile name="test">
+        <logger name="com.tzld.piaoquan.recommend.server" level="info"/>
+    </springProfile>
+    <springProfile name="pre">
+        <logger name="com.tzld.piaoquan.recommend.server" level="info"/>
+    </springProfile>
+    <springProfile name="stress">
+        <logger name="com.tzld.piaoquan.recommend.server" level="info"/>
+    </springProfile>
+    <springProfile name="prod">
+        <logger name="com.tzld.piaoquan.recommend.server" level="info"/>
+    </springProfile>
+
+    <root level="info">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="DEBUG_FILE"/>
+        <appender-ref ref="INFO_FILE"/>
+        <appender-ref ref="WARN_FILE"/>
+        <appender-ref ref="ERROR_FILE"/>
+        <appender-ref ref="loghubAppenderInfo"/>
+        <appender-ref ref="loghubAppenderWarn"/>
+        <appender-ref ref="loghubAppenderError"/>
+    </root>
+
+</configuration>

+ 304 - 0
long-article-recommend-service/src/test/java/com/tzld/piaoquan/recommend/test/merger/MergeUtilsTest.java

@@ -0,0 +1,304 @@
+package com.tzld.longarticle.recommend.test.merger;
+
+import com.tzld.piaoquan.recommend.feature.client.FeatureClient;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;
+
+
+
+import com.tzld.piaoquan.recommend.server.common.base.RankItem;
+import com.tzld.piaoquan.recommend.server.framework.common.User;
+import com.tzld.piaoquan.recommend.server.framework.merger.MergeRule;
+import com.tzld.piaoquan.recommend.server.framework.merger.MergeUtils;
+import com.tzld.piaoquan.recommend.server.framework.merger.SimilarityUtils;
+import com.tzld.piaoquan.recommend.server.gen.recommend.RecommendRequest;
+import org.apache.commons.lang3.tuple.Pair;
+//import org.junit.Assert;
+//import org.junit.Test;
+import com.google.common.base.Function;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class MergeUtilsTest {
+
+//    @Test
+    public void mergeWithProtectionTest() {
+        User user = new User();
+
+        Map<String, Pair<MergeRule, List<RankItem>>> rankerItemsList = new HashMap<String, Pair<MergeRule, List<RankItem>>>();
+        MergeRule rule1 = new MergeRule();
+        rule1.queueName = "rule1";
+        rule1.minMergeNum = 2;
+        // 构建一个队列的ranklist
+        List<RankItem> items1 = new LinkedList<RankItem>();
+        RankItem item11 = new RankItem();
+        item11.setScore(0.1);
+        items1.add(item11);
+        rankerItemsList.put(rule1.queueName, Pair.of(rule1, items1));
+
+        List<RankItem> resultItems = new LinkedList<RankItem>();
+        MergeUtils.simpleMergeWithProtection(resultItems, rankerItemsList, 2, 0);
+//        Assert.assertTrue(resultItems.size() == 1);
+
+
+        RankItem item12 = new RankItem();
+        item12.setScore(0.2);
+        // list增加第二个
+        items1.add(item12);
+        resultItems.clear();
+        MergeUtils.simpleMergeWithProtection(resultItems, rankerItemsList, 2, 1);
+
+        // 判断是否受到最小合并控制, 插入两个,召回两个
+//        Assert.assertTrue(resultItems.size() == 2);
+        resultItems.clear();
+
+        // 插入两个,召回三个
+        MergeUtils.simpleMergeWithProtection(resultItems, rankerItemsList, 3, 0);
+//        Assert.assertTrue(resultItems.size() == 2);
+
+        // 最小合并条目保护,因为min mergenum 是2
+        resultItems.clear();
+        MergeUtils.simpleMergeWithProtection(resultItems, rankerItemsList, 1, 0);
+//        Assert.assertTrue(resultItems.size() == 2);
+
+        // 第二个list
+        List<RankItem> items2 = new LinkedList<RankItem>();
+        RankItem item21 = new RankItem();
+        // 一个item
+        item21.setScore(0.12);
+        items2.add(item21);
+
+        // 第二个rules
+        MergeRule rule2 = new MergeRule();
+        rule2.queueName = "rule2";
+        rule2.minMergeNum = 0;
+        // 加入第二个rule
+        rankerItemsList.put(rule2.queueName, Pair.of(rule2, items2));
+        resultItems.clear();
+        // 共同合并,因为rule2 min MergeNum =0,合并完只有两个
+        MergeUtils.simpleMergeWithProtection(resultItems, rankerItemsList, 2, 0);
+//        Assert.assertTrue(resultItems.size() == 2);
+
+        // 共同合并,rule2最小合并1个,因为rule1是1个,所以合并完是3个
+        rule2.minMergeNum = 1;
+        resultItems.clear();
+        MergeUtils.simpleMergeWithProtection(resultItems, rankerItemsList, 2, 0);
+//        Assert.assertTrue(resultItems.size() == 3);
+
+        // 第三个list, 3个item
+        List<RankItem> items3 = new LinkedList<RankItem>();
+        RankItem item31 = new RankItem();
+        item31.setScore(0.113);
+        items3.add(item31);
+        RankItem item32 = new RankItem();
+        item32.setScore(0.114);
+        items3.add(item31);
+        RankItem item33 = new RankItem();
+        item33.setScore(0.123);
+        items3.add(item31);
+
+        // 第三个rule,最小merge 1
+        MergeRule rule3 = new MergeRule();
+        rule3.queueName = "rule3";
+        rule3.minMergeNum = 1;
+        rankerItemsList.put(rule3.queueName, Pair.of(rule3, items3));
+        resultItems.clear();
+        // rule1 2个,rule2 1个,rule3 1个,所以合并完是4个
+        MergeUtils.simpleMergeWithProtection(resultItems, rankerItemsList, 2, 0);
+//        Assert.assertTrue(resultItems.size() == 4);
+    }
+
+    private List<RankItem> getItems() {
+        List<RankItem> items = new LinkedList<RankItem>();
+        RankItem item11 = new RankItem();
+        item11.setId("11");
+        item11.setScore(100.0);
+        Map<String, Double> categories11 = new HashMap<String, Double>();
+        categories11.put("美女", 100.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("22");
+        item11.setScore(99.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("动物", 99.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("33");
+        item11.setScore(98.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("美女", 98.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setScore(97.0);
+        item11.setId("44");
+        categories11 = new HashMap<String, Double>();
+        categories11.put("美女", 97.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("55");
+        item11.setScore(96.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("动物", 96.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("66");
+        item11.setScore(95.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("美女", 95.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("77");
+        item11.setScore(94.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("动物", 94.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("88");
+        item11.setScore(93.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("美女", 93.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("99");
+        item11.setScore(92.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("动物", 92.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("100");
+        item11.setScore(91.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("动物", 91.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("101");
+        item11.setScore(90.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("美女", 90.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("102");
+        item11.setScore(89.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("动物", 89.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("103");
+        item11.setScore(88.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("美女", 88.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        item11 = new RankItem();
+        item11.setId("104");
+        item11.setScore(87.0);
+        categories11 = new HashMap<String, Double>();
+        categories11.put("美女", 87.0);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        return items;
+    }
+
+//    @Test
+    public void testDiversityRerank() {
+        List<RankItem> items = new LinkedList<RankItem>();
+
+        Function<Pair<RankItem, RankItem>, Boolean> isSameCategoryFunc = SimilarityUtils.getIsSameCategoryFunc();
+
+        RankItem item11 = new RankItem();
+        Map<String, Double> categories11 = new HashMap<String, Double>();
+        categories11.put("1", 0.1);
+        item11.setRankItemCategories(categories11);
+        items.add(item11);
+
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 1, 1, 1);
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 2, 1, 1);
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 2, 2, 1);
+
+        RankItem item12 = new RankItem();
+        Map<String, Double> categories12 = new HashMap<String, Double>();
+        categories12.put("1", 0.1);
+        item12.setRankItemCategories(categories12);
+        item12.setScore(0.2);
+        items.add(item12);
+
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 2, 2, 1);
+//        Assert.assertTrue(SimilarityUtils.isSameCategory(items.get(0), items.get(1)));
+
+        RankItem item13 = new RankItem();
+        Map<String, Double> categories13 = new HashMap<String, Double>();
+        categories13.put("2", 0.1);
+        item13.setRankItemCategories(categories13);
+        items.add(item13);
+
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 2, 2, 2);
+//        Assert.assertTrue(SimilarityUtils.isSameCategory(items.get(0), items.get(1)));
+
+        RankItem item14 = new RankItem();
+        Map<String, Double> categories14 = new HashMap<String, Double>();
+        categories14.put("1", 0.1);
+        item14.setRankItemCategories(categories14);
+        items.add(item14);
+
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 3, 2, 2);
+//        Assert.assertTrue(SimilarityUtils.isSameCategory(items.get(0), items.get(1)));
+
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 3, 2, 1);
+//        Assert.assertTrue(SimilarityUtils.isSameCategory(items.get(0), items.get(1)) == false);
+
+        RankItem item15 = new RankItem();
+        Map<String, Double> categories15 = new HashMap<String, Double>();
+        categories15.put("2", 0.1);
+        item15.setRankItemCategories(categories15);
+        items.add(item15);
+
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 4, 2, 2);
+//        Assert.assertTrue(SimilarityUtils.isSameCategory(items.get(0), items.get(3)));
+
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 4, 3, 2);
+//        Assert.assertTrue(SimilarityUtils.isSameCategory(items.get(0), items.get(3)));
+
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 4, 4, 2);
+//        Assert.assertTrue(SimilarityUtils.isSameCategory(items.get(0), items.get(3)) == false);
+
+        items = getItems();
+        MergeUtils.diversityRerank(items, isSameCategoryFunc, 8, 8, 2);
+//        Assert.assertTrue(SimilarityUtils.isSameCategory(items.get(0), items.get(3)) == false);
+//        Assert.assertTrue(SimilarityUtils.isSameCategory(items.get(3), items.get(5)) == false);
+    }
+}

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
long-article-recommend-service/target/classes/20240609_bucket_274.txt


+ 136 - 0
long-article-recommend-service/target/classes/application-dev.yml

@@ -0,0 +1,136 @@
+server:
+  port: 8001
+
+eureka:
+  instance:
+    prefer-ip-address: true #是否优先使用IP地址作为主机名的标识,默认false
+    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} #注册到eureka上的唯一实例ID
+    lease-renewal-interval-in-seconds: 10 #表示eureka client发送心跳给server端的频率,默认30
+    lease-expiration-duration-in-seconds: 30 #表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance,默认90
+  client:
+    registry-fetch-interval-seconds: 5  #定时从Eureka Server拉取服务注册信息的间隔时间
+    serviceUrl:
+      defaultZone: http://deveureka-internal.piaoquantv.com/eureka/
+
+spring:
+  redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  feature-redis:
+    hostName: r-bp1pi8wyv6lzvgjy5z.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  long-video-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  filter-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  video-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  data:
+    mongodb:
+      clusterHost: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com
+      clusterPort: 3717
+      secondaryHost: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com
+      secondaryPort: 3717
+      database: longvideo
+      username: lv
+      password: lv@2018
+      replicaSetName: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com:3717,dds-bp1de4fc73029b242144.mongodb.rds.aliyuncs.com:3717
+      # 连接池
+      maxConnectionIdleTime: 180000
+      # maxConnectionLifeTime: 30000
+      maxWaitTime: 3000
+      minSize: 5
+      maxSize: 10
+  datasource:
+    url: jdbc:mysql://rm-bp1k5853td1r25g3n690.mysql.rds.aliyuncs.com:3306/longvideo?useSSL=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
+    username: wx2016_longvideo
+    password: wx2016_longvideoP@assword1234
+    driver-class-name: com.mysql.jdbc.Driver
+    hikari:
+      connection-timeout: 30000
+      minimum-idle: 5
+      maximum-pool-size: 10
+      auto-commit: true
+      idle-timeout: 30000
+  jpa:
+    hibernate:
+      ddl-auto: validate
+    database: mysql
+xxl:
+  job:
+    admin:
+      addresses: http://xxl-job-test-internal.piaoquantv.com/xxl-job-admin
+    accessToken:
+    executor:
+      appname: ${spring.application.name}
+      address:
+      ip:
+      port: 9999
+      logpath: /datalog/weblog/${spring.application.name}/xxl-job/
+      logretentiondays: 30
+
+apollo:
+  meta: http://devapolloconfig-internal.piaoquantv.com
+
+aliyun:
+  log:
+    endpoint: cn-hangzhou.log.aliyuncs.com
+    accessKeyId: LTAIP6x1l3DXfSxm
+    accessKeySecret: KbTaM9ars4OX3PMS6Xm7rtxGr1FLon
+    project: recommend-server-test
+  timer:
+    log:
+      project: recommend-server-test
+      logStore: timer
+  blacklist:
+    filter:
+      log:
+        project: wqsd-video-test
+        store: video_blacklist_security_filter_log
+
+logging:
+  file:
+    path: ./${spring.application.name}/logs/

+ 131 - 0
long-article-recommend-service/target/classes/application-pre.yml

@@ -0,0 +1,131 @@
+server:
+  port: 8080
+
+eureka:
+  instance:
+    prefer-ip-address: true #是否优先使用IP地址作为主机名的标识,默认false
+    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} #注册到eureka上的唯一实例ID
+    lease-renewal-interval-in-seconds: 10 #表示eureka client发送心跳给server端的频率,默认30
+    lease-expiration-duration-in-seconds: 30 #表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance,默认90
+  client:
+    registry-fetch-interval-seconds: 5  #定时从Eureka Server拉取服务注册信息的间隔时间
+    serviceUrl:
+      defaultZone: http://preeureka-internal.piaoquantv.com/eureka/
+
+spring:
+  redis:
+    hostName: r-bp1fogs2mflr1ybfot.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  feature-redis:
+    hostName: r-bp1pi8wyv6lzvgjy5z.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  long-video-redis:
+    hostName: r-bp1oyhyx4mxgs6klyt561.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  filter-redis:
+    hostName: r-bp109v1gjl63qi00cb.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  video-redis:
+    hostName: r-bp1f3341ec15a634301.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  data:
+    mongodb:
+      clusterHost: s-bp14ce206f81b754.mongodb.rds.aliyuncs.com
+      clusterPort: 3717
+      secondaryHost: s-bp137073555e7bc4.mongodb.rds.aliyuncs.com
+      secondaryPort: 3717
+      database: longvideo
+      username: lv
+      password: lv2018
+      # 连接池
+      maxConnectionIdleTime: 180000
+      # maxConnectionLifeTime: 30000
+      maxWaitTime: 5000
+      minSize: 5
+      maxSize: 100
+  datasource:
+    url: jdbc:mysql://rm-bp1jjv3jv98133plv285-vpc-rw.mysql.rds.aliyuncs.com:3306/longvideo?useSSL=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
+    username: wx2016_longvideo
+    password: wx2016_longvideoP@assword1234
+    driver-class-name: com.mysql.jdbc.Driver
+    hikari:
+      connection-timeout: 30000
+      minimum-idle: 5
+      maximum-pool-size: 10
+      auto-commit: true
+      idle-timeout: 30000
+  jpa:
+    hibernate:
+      ddl-auto: validate
+    database: mysql
+xxl:
+  job:
+    admin:
+      addresses: http://xxl-job-pre-internal.piaoquantv.com/xxl-job-admin
+    accessToken:
+    executor:
+      appname: ${spring.application.name}
+      address:
+      ip:
+      port: 9999
+      logpath: /datalog/weblog/${spring.application.name}/xxl-job/
+      logretentiondays: 30
+
+apollo:
+  meta: http://preapolloconfig-internal.piaoquantv.com
+
+aliyun:
+  log:
+    endpoint: cn-hangzhou-intranet.log.aliyuncs.com
+    accessKeyId: LTAIP6x1l3DXfSxm
+    accessKeySecret: KbTaM9ars4OX3PMS6Xm7rtxGr1FLon
+    project: recommend-server
+  timer:
+    log:
+      project: recommend-server
+      logStore: timer
+  blacklist:
+    filter:
+      log:
+        project: wqsd-video
+        store: video_blacklist_security_filter_log

+ 131 - 0
long-article-recommend-service/target/classes/application-prod.yml

@@ -0,0 +1,131 @@
+server:
+  port: 8080
+
+eureka:
+  instance:
+    prefer-ip-address: true #是否优先使用IP地址作为主机名的标识,默认false
+    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} #注册到eureka上的唯一实例ID
+    lease-renewal-interval-in-seconds: 10 #表示eureka client发送心跳给server端的频率,默认30
+    lease-expiration-duration-in-seconds: 30 #表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance,默认90
+  client:
+    registry-fetch-interval-seconds: 5  #定时从Eureka Server拉取服务注册信息的间隔时间
+    serviceUrl:
+      defaultZone: http://eureka-internal.piaoquantv.com/eureka/
+
+spring:
+  redis:
+    hostName: r-bp1fogs2mflr1ybfot.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  feature-redis:
+    hostName: r-bp1pi8wyv6lzvgjy5z.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  long-video-redis:
+    hostName: r-bp1oyhyx4mxgs6klyt561.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  filter-redis:
+    hostName: r-bp109v1gjl63qi00cb.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  video-redis:
+    hostName: r-bp1f3341ec15a634301.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  data:
+    mongodb:
+      clusterHost: s-bp14ce206f81b754.mongodb.rds.aliyuncs.com
+      clusterPort: 3717
+      secondaryHost: s-bp137073555e7bc4.mongodb.rds.aliyuncs.com
+      secondaryPort: 3717
+      database: longvideo
+      username: lv
+      password: lv2018
+      # 连接池
+      maxConnectionIdleTime: 180000
+      # maxConnectionLifeTime: 30000
+      maxWaitTime: 5000
+      minSize: 5
+      maxSize: 100
+  datasource:
+    url: jdbc:mysql://rm-bp1jjv3jv98133plv285-vpc-rw.mysql.rds.aliyuncs.com:3306/longvideo?useSSL=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
+    username: wx2016_longvideo
+    password: wx2016_longvideoP@assword1234
+    driver-class-name: com.mysql.jdbc.Driver
+    hikari:
+      connection-timeout: 30000
+      minimum-idle: 5
+      maximum-pool-size: 100
+      auto-commit: true
+      idle-timeout: 30000
+  jpa:
+    hibernate:
+      ddl-auto: validate
+    database: mysql
+xxl:
+  job:
+    admin:
+      addresses: http://192.168.201.25:8182/xxl-job-admin
+    accessToken:
+    executor:
+      appname: ${spring.application.name}
+      address:
+      ip:
+      port: 9999
+      logpath: /datalog/weblog/${spring.application.name}/xxl-job/
+      logretentiondays: 30
+
+apollo:
+  meta: http://apolloconfig-internal.piaoquantv.com
+
+aliyun:
+  log:
+    endpoint: cn-hangzhou-intranet.log.aliyuncs.com
+    accessKeyId: LTAIP6x1l3DXfSxm
+    accessKeySecret: KbTaM9ars4OX3PMS6Xm7rtxGr1FLon
+    project: recommend-server
+  timer:
+    log:
+      project: recommend-server
+      logStore: timer
+  blacklist:
+    filter:
+      log:
+        project: wqsd-video
+        store: video_blacklist_security_filter_log

+ 132 - 0
long-article-recommend-service/target/classes/application-test.yml

@@ -0,0 +1,132 @@
+server:
+  port: 8080
+
+eureka:
+  instance:
+    prefer-ip-address: true #是否优先使用IP地址作为主机名的标识,默认false
+    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} #注册到eureka上的唯一实例ID
+    lease-renewal-interval-in-seconds: 10 #表示eureka client发送心跳给server端的频率,默认30
+    lease-expiration-duration-in-seconds: 30 #表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance,默认90
+  client:
+    registry-fetch-interval-seconds: 5  #定时从Eureka Server拉取服务注册信息的间隔时间
+    serviceUrl:
+      defaultZone: http://testeureka-internal.piaoquantv.com/eureka/
+
+spring:
+  redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  feature-redis:
+    hostName: r-bp1pi8wyv6lzvgjy5z.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  long-video-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  filter-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  video-redis:
+    hostName: r-bp1ps6my7lzg8rdhwx682.redis.rds.aliyuncs.com
+    port: 6379
+    password: Wqsd@2019
+    timeout: 1000
+    lettuce:
+      pool:
+        max-active: 8
+        max-wait: -1
+        max-idle: 8
+        min-idle: 0
+  data:
+    mongodb:
+      clusterHost: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com
+      clusterPort: 3717
+      secondaryHost: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com
+      secondaryPort: 3717
+      database: longvideo
+      username: lv
+      password: lv@2018
+      replicaSetName: dds-bp1de4fc73029b241978.mongodb.rds.aliyuncs.com:3717,dds-bp1de4fc73029b242144.mongodb.rds.aliyuncs.com:3717
+      # 连接池
+      maxConnectionIdleTime: 180000
+      # maxConnectionLifeTime: 30000
+      maxWaitTime: 3000
+      minSize: 5
+      maxSize: 10
+  datasource:
+    url: jdbc:mysql://rm-bp1k5853td1r25g3n690.mysql.rds.aliyuncs.com:3306/longvideo?useSSL=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
+    username: wx2016_longvideo
+    password: wx2016_longvideoP@assword1234
+    driver-class-name: com.mysql.jdbc.Driver
+    hikari:
+      connection-timeout: 30000
+      minimum-idle: 5
+      maximum-pool-size: 10
+      auto-commit: true
+      idle-timeout: 30000
+  jpa:
+    hibernate:
+      ddl-auto: validate
+    database: mysql
+xxl:
+  job:
+    admin:
+      addresses: http://xxl-job-test-internal.piaoquantv.com/xxl-job-admin
+    accessToken:
+    executor:
+      appname: ${spring.application.name}
+      address:
+      ip:
+      port: 9999
+      logpath: /datalog/weblog/${spring.application.name}/xxl-job/
+      logretentiondays: 30
+
+apollo:
+  meta: http://testapolloconfig-internal.piaoquantv.com
+
+aliyun:
+  log:
+    endpoint: cn-hangzhou-intranet.log.aliyuncs.com
+    accessKeyId: LTAIP6x1l3DXfSxm
+    accessKeySecret: KbTaM9ars4OX3PMS6Xm7rtxGr1FLon
+    project: recommend-server-test
+  timer:
+    log:
+      project: recommend-server-test
+      logStore: timer
+  blacklist:
+    filter:
+      log:
+        project: wqsd-video-test
+        store: video_blacklist_security_filter_log

+ 61 - 0
long-article-recommend-service/target/classes/application.yml

@@ -0,0 +1,61 @@
+spring:
+  profiles:
+    active: dev
+  application:
+    name: recommend-server
+#  cloud:
+#    sentinel:
+#      eager: true
+#      transport:
+#        port: 8719
+#      log:
+#        dir: /datalog/sentinel
+#      datasource:
+#        ds1:
+#          apollo:
+#            namespace-name: application
+#            flow-rules-key: sentinel.flowRules
+#            default-flow-rule-value: []
+#            rule-type: flow
+grpc:
+  server:
+    port: 9001
+    reflection-service-enabled: true
+  client:
+    recommend-feature:
+      negotiationType: PLAINTEXT
+    abtest:
+      negotiationType: PLAINTEXT
+
+server:
+  tomcat:
+    threads:
+      max: 1000
+    uri-encoding: UTF-8
+    accept-count: 1000
+    connection-timeout: 30000
+  servlet:
+    context-path: /recommend-server
+    session:
+      timeout: 60
+pagehelper:
+  helper-dialect: mysql
+
+logging:
+  file:
+    path: /datalog/weblog/${spring.application.name}/
+
+app:
+  id: recommend-server
+apollo:
+  bootstrap:
+    enabled: true
+    namespaces: application,RD.Experiment
+  cacheDir: /datalog/apollo-cache-dir
+
+feign:
+  client:
+    config:
+      default:
+        connectTimeout: 2000
+        readTimeout: 10000

+ 6 - 0
long-article-recommend-service/target/classes/attention_config.conf

@@ -0,0 +1,6 @@
+attention-extractor-config = {
+  categories-by-ctr-extractor = {
+    name = "com.tzld.piaoquan.recommend.server.implement.attention.SimpleAttentionExtractor"
+  }
+
+}

BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/Application.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/CommonThreadPoolExecutor.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/RecommendLoghubAppender.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/RecommendLoghubAppenderCallback.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/ThreadPoolFactory.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/base/Constant.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/base/RankItem.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/base/VideoActionFeature.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/common/enums/AppTypeEnum.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/CustomMongoProperties.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/FeatureRedisTemplateConfig.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/FilterRedisTemplateConfig.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/LongVideoRedisTemplateConfig.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/MongoTemplateConfig.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/RedisTemplateConfig.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/VideoRedisTemplateConfig.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/config/XxlJobConfig.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/dataloader/FeatureConstructor.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/dataloader/ItemFeatureToRedisLoader.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/dataloader/OfflineAdOutSamplesLoader.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/dataloader/UserFeatureToRedisLoader.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/candidiate/Candidate.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/candidiate/CandidateInfo.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/candidiate/Entry.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/candidiate/Queue.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/candidiate/QueueName.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/common/User.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/common/UserAction.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/common/UserAttention.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/IndexCandidateQueue.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/MergeRule.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/MergeUtils.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/SimilarityUtils.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/SimpleMergeQueue.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/StrategyQueue.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/StrategyQueueConfig.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/merger/StrategyQueueInfo.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/GBDTModel.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/LRModel.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/Model.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/ModelManager.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/OssConfig.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/model/ThompsonSamplingModel.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/recaller/AbstractFilter.class


BIN
long-article-recommend-service/target/classes/com/tzld/piaoquan/recommend/server/framework/recaller/BaseRecaller.class


Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott