丁云鹏 1 рік тому
батько
коміт
41cc91f888
18 змінених файлів з 5100 додано та 387 видалено
  1. 819 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/BaseFeature.java
  2. 45 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/BaseFeatureOrBuilder.java
  3. 104 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/CtrSamples.java
  4. 897 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/FeatureGroup.java
  5. 51 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/FeatureGroupOrBuilder.java
  6. 1022 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/GroupedFeature.java
  7. 54 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/GroupedFeatureOrBuilder.java
  8. 1094 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/LRSamples.java
  9. 63 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/LRSamplesOrBuilder.java
  10. 834 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/LRWeight.java
  11. 39 0
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/LRWeightOrBuilder.java
  12. 15 10
      recommend-server-service/pom.xml
  13. 1 15
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/VlogShareLRScorer.java
  14. 0 5
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/GBDTModel.java
  15. 7 259
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/LRModel.java
  16. 0 2
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/Model.java
  17. 40 96
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/ModelManager.java
  18. 15 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/OssConfig.java

+ 819 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/BaseFeature.java

@@ -0,0 +1,819 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+/**
+ * Protobuf type {@code BaseFeature}
+ */
+public final class BaseFeature extends
+    com.google.protobuf.GeneratedMessageV3 implements
+    // @@protoc_insertion_point(message_implements:BaseFeature)
+    BaseFeatureOrBuilder {
+private static final long serialVersionUID = 0L;
+  // Use BaseFeature.newBuilder() to construct.
+  private BaseFeature(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+  private BaseFeature() {
+    fea_ = "";
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(
+      UnusedPrivateParameter unused) {
+    return new BaseFeature();
+  }
+
+  @java.lang.Override
+  public final com.google.protobuf.UnknownFieldSet
+  getUnknownFields() {
+    return this.unknownFields;
+  }
+  private BaseFeature(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    this();
+    if (extensionRegistry == null) {
+      throw new java.lang.NullPointerException();
+    }
+    com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+        com.google.protobuf.UnknownFieldSet.newBuilder();
+    try {
+      boolean done = false;
+      while (!done) {
+        int tag = input.readTag();
+        switch (tag) {
+          case 0:
+            done = true;
+            break;
+          case 8: {
+
+            id_ = input.readInt64();
+            break;
+          }
+          case 16: {
+
+            identifier_ = input.readInt64();
+            break;
+          }
+          case 26: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            fea_ = s;
+            break;
+          }
+          case 33: {
+
+            value_ = input.readDouble();
+            break;
+          }
+          case 41: {
+
+            weight_ = input.readDouble();
+            break;
+          }
+          default: {
+            if (!parseUnknownField(
+                input, unknownFields, extensionRegistry, tag)) {
+              done = true;
+            }
+            break;
+          }
+        }
+      }
+    } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(this);
+    } catch (java.io.IOException e) {
+      throw new com.google.protobuf.InvalidProtocolBufferException(
+          e).setUnfinishedMessage(this);
+    } finally {
+      this.unknownFields = unknownFields.build();
+      makeExtensionsImmutable();
+    }
+  }
+  public static final com.google.protobuf.Descriptors.Descriptor
+      getDescriptor() {
+    return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_BaseFeature_descriptor;
+  }
+
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_BaseFeature_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.class, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder.class);
+  }
+
+  public static final int ID_FIELD_NUMBER = 1;
+  private long id_;
+  /**
+   * <code>int64 id = 1;</code>
+   * @return The id.
+   */
+  @java.lang.Override
+  public long getId() {
+    return id_;
+  }
+
+  public static final int IDENTIFIER_FIELD_NUMBER = 2;
+  private long identifier_;
+  /**
+   * <code>int64 identifier = 2;</code>
+   * @return The identifier.
+   */
+  @java.lang.Override
+  public long getIdentifier() {
+    return identifier_;
+  }
+
+  public static final int FEA_FIELD_NUMBER = 3;
+  private volatile java.lang.Object fea_;
+  /**
+   * <code>string fea = 3;</code>
+   * @return The fea.
+   */
+  @java.lang.Override
+  public java.lang.String getFea() {
+    java.lang.Object ref = fea_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      fea_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string fea = 3;</code>
+   * @return The bytes for fea.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getFeaBytes() {
+    java.lang.Object ref = fea_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      fea_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int VALUE_FIELD_NUMBER = 4;
+  private double value_;
+  /**
+   * <code>double value = 4;</code>
+   * @return The value.
+   */
+  @java.lang.Override
+  public double getValue() {
+    return value_;
+  }
+
+  public static final int WEIGHT_FIELD_NUMBER = 5;
+  private double weight_;
+  /**
+   * <code>double weight = 5;</code>
+   * @return The weight.
+   */
+  @java.lang.Override
+  public double getWeight() {
+    return weight_;
+  }
+
+  private byte memoizedIsInitialized = -1;
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output)
+                      throws java.io.IOException {
+    if (id_ != 0L) {
+      output.writeInt64(1, id_);
+    }
+    if (identifier_ != 0L) {
+      output.writeInt64(2, identifier_);
+    }
+    if (!getFeaBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 3, fea_);
+    }
+    if (value_ != 0D) {
+      output.writeDouble(4, value_);
+    }
+    if (weight_ != 0D) {
+      output.writeDouble(5, weight_);
+    }
+    unknownFields.writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    if (id_ != 0L) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt64Size(1, id_);
+    }
+    if (identifier_ != 0L) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt64Size(2, identifier_);
+    }
+    if (!getFeaBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, fea_);
+    }
+    if (value_ != 0D) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeDoubleSize(4, value_);
+    }
+    if (weight_ != 0D) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeDoubleSize(5, weight_);
+    }
+    size += unknownFields.getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+     return true;
+    }
+    if (!(obj instanceof com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature)) {
+      return super.equals(obj);
+    }
+    com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature other = (com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature) obj;
+
+    if (getId()
+        != other.getId()) return false;
+    if (getIdentifier()
+        != other.getIdentifier()) return false;
+    if (!getFea()
+        .equals(other.getFea())) return false;
+    if (java.lang.Double.doubleToLongBits(getValue())
+        != java.lang.Double.doubleToLongBits(
+            other.getValue())) return false;
+    if (java.lang.Double.doubleToLongBits(getWeight())
+        != java.lang.Double.doubleToLongBits(
+            other.getWeight())) return false;
+    if (!unknownFields.equals(other.unknownFields)) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    hash = (37 * hash) + ID_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        getId());
+    hash = (37 * hash) + IDENTIFIER_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        getIdentifier());
+    hash = (37 * hash) + FEA_FIELD_NUMBER;
+    hash = (53 * hash) + getFea().hashCode();
+    hash = (37 * hash) + VALUE_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        java.lang.Double.doubleToLongBits(getValue()));
+    hash = (37 * hash) + WEIGHT_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        java.lang.Double.doubleToLongBits(getWeight()));
+    hash = (29 * hash) + unknownFields.hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseFrom(
+      java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseFrom(
+      java.nio.ByteBuffer data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseFrom(
+      com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseFrom(
+      byte[] data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseDelimitedFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseFrom(
+      com.google.protobuf.CodedInputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() { return newBuilder(); }
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+  public static Builder newBuilder(com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE
+        ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(
+      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   * Protobuf type {@code BaseFeature}
+   */
+  public static final class Builder extends
+      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+      // @@protoc_insertion_point(builder_implements:BaseFeature)
+      com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_BaseFeature_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_BaseFeature_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.class, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder.class);
+    }
+
+    // Construct using com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.newBuilder()
+    private Builder() {
+      maybeForceBuilderInitialization();
+    }
+
+    private Builder(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+      maybeForceBuilderInitialization();
+    }
+    private void maybeForceBuilderInitialization() {
+      if (com.google.protobuf.GeneratedMessageV3
+              .alwaysUseFieldBuilders) {
+      }
+    }
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      id_ = 0L;
+
+      identifier_ = 0L;
+
+      fea_ = "";
+
+      value_ = 0D;
+
+      weight_ = 0D;
+
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor
+        getDescriptorForType() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_BaseFeature_descriptor;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature getDefaultInstanceForType() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature build() {
+      com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature buildPartial() {
+      com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature result = new com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature(this);
+      result.id_ = id_;
+      result.identifier_ = identifier_;
+      result.fea_ = fea_;
+      result.value_ = value_;
+      result.weight_ = weight_;
+      onBuilt();
+      return result;
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.setField(field, value);
+    }
+    @java.lang.Override
+    public Builder clearField(
+        com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+    @java.lang.Override
+    public Builder clearOneof(
+        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature) {
+        return mergeFrom((com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature)other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature other) {
+      if (other == com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.getDefaultInstance()) return this;
+      if (other.getId() != 0L) {
+        setId(other.getId());
+      }
+      if (other.getIdentifier() != 0L) {
+        setIdentifier(other.getIdentifier());
+      }
+      if (!other.getFea().isEmpty()) {
+        fea_ = other.fea_;
+        onChanged();
+      }
+      if (other.getValue() != 0D) {
+        setValue(other.getValue());
+      }
+      if (other.getWeight() != 0D) {
+        setWeight(other.getWeight());
+      }
+      this.mergeUnknownFields(other.unknownFields);
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature parsedMessage = null;
+      try {
+        parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        parsedMessage = (com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature) e.getUnfinishedMessage();
+        throw e.unwrapIOException();
+      } finally {
+        if (parsedMessage != null) {
+          mergeFrom(parsedMessage);
+        }
+      }
+      return this;
+    }
+
+    private long id_ ;
+    /**
+     * <code>int64 id = 1;</code>
+     * @return The id.
+     */
+    @java.lang.Override
+    public long getId() {
+      return id_;
+    }
+    /**
+     * <code>int64 id = 1;</code>
+     * @param value The id to set.
+     * @return This builder for chaining.
+     */
+    public Builder setId(long value) {
+      
+      id_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int64 id = 1;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearId() {
+      
+      id_ = 0L;
+      onChanged();
+      return this;
+    }
+
+    private long identifier_ ;
+    /**
+     * <code>int64 identifier = 2;</code>
+     * @return The identifier.
+     */
+    @java.lang.Override
+    public long getIdentifier() {
+      return identifier_;
+    }
+    /**
+     * <code>int64 identifier = 2;</code>
+     * @param value The identifier to set.
+     * @return This builder for chaining.
+     */
+    public Builder setIdentifier(long value) {
+      
+      identifier_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int64 identifier = 2;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearIdentifier() {
+      
+      identifier_ = 0L;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object fea_ = "";
+    /**
+     * <code>string fea = 3;</code>
+     * @return The fea.
+     */
+    public java.lang.String getFea() {
+      java.lang.Object ref = fea_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        fea_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string fea = 3;</code>
+     * @return The bytes for fea.
+     */
+    public com.google.protobuf.ByteString
+        getFeaBytes() {
+      java.lang.Object ref = fea_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        fea_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string fea = 3;</code>
+     * @param value The fea to set.
+     * @return This builder for chaining.
+     */
+    public Builder setFea(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      fea_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string fea = 3;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearFea() {
+      
+      fea_ = getDefaultInstance().getFea();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string fea = 3;</code>
+     * @param value The bytes for fea to set.
+     * @return This builder for chaining.
+     */
+    public Builder setFeaBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      fea_ = value;
+      onChanged();
+      return this;
+    }
+
+    private double value_ ;
+    /**
+     * <code>double value = 4;</code>
+     * @return The value.
+     */
+    @java.lang.Override
+    public double getValue() {
+      return value_;
+    }
+    /**
+     * <code>double value = 4;</code>
+     * @param value The value to set.
+     * @return This builder for chaining.
+     */
+    public Builder setValue(double value) {
+      
+      value_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>double value = 4;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearValue() {
+      
+      value_ = 0D;
+      onChanged();
+      return this;
+    }
+
+    private double weight_ ;
+    /**
+     * <code>double weight = 5;</code>
+     * @return The weight.
+     */
+    @java.lang.Override
+    public double getWeight() {
+      return weight_;
+    }
+    /**
+     * <code>double weight = 5;</code>
+     * @param value The weight to set.
+     * @return This builder for chaining.
+     */
+    public Builder setWeight(double value) {
+      
+      weight_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>double weight = 5;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearWeight() {
+      
+      weight_ = 0D;
+      onChanged();
+      return this;
+    }
+    @java.lang.Override
+    public final Builder setUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+
+    // @@protoc_insertion_point(builder_scope:BaseFeature)
+  }
+
+  // @@protoc_insertion_point(class_scope:BaseFeature)
+  private static final com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature DEFAULT_INSTANCE;
+  static {
+    DEFAULT_INSTANCE = new com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature();
+  }
+
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<BaseFeature>
+      PARSER = new com.google.protobuf.AbstractParser<BaseFeature>() {
+    @java.lang.Override
+    public BaseFeature parsePartialFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return new BaseFeature(input, extensionRegistry);
+    }
+  };
+
+  public static com.google.protobuf.Parser<BaseFeature> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<BaseFeature> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+
+}
+

+ 45 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/BaseFeatureOrBuilder.java

@@ -0,0 +1,45 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+public interface BaseFeatureOrBuilder extends
+    // @@protoc_insertion_point(interface_extends:BaseFeature)
+    com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>int64 id = 1;</code>
+   * @return The id.
+   */
+  long getId();
+
+  /**
+   * <code>int64 identifier = 2;</code>
+   * @return The identifier.
+   */
+  long getIdentifier();
+
+  /**
+   * <code>string fea = 3;</code>
+   * @return The fea.
+   */
+  java.lang.String getFea();
+  /**
+   * <code>string fea = 3;</code>
+   * @return The bytes for fea.
+   */
+  com.google.protobuf.ByteString
+      getFeaBytes();
+
+  /**
+   * <code>double value = 4;</code>
+   * @return The value.
+   */
+  double getValue();
+
+  /**
+   * <code>double weight = 5;</code>
+   * @return The weight.
+   */
+  double getWeight();
+}

+ 104 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/CtrSamples.java

@@ -0,0 +1,104 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+public final class CtrSamples {
+  private CtrSamples() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistryLite registry) {
+  }
+
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+    registerAllExtensions(
+        (com.google.protobuf.ExtensionRegistryLite) registry);
+  }
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_FeatureGroup_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_FeatureGroup_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_BaseFeature_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_BaseFeature_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_GroupedFeature_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_GroupedFeature_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_LRWeight_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_LRWeight_fieldAccessorTable;
+  static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_LRSamples_descriptor;
+  static final 
+    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internal_static_LRSamples_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static  com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n4com/tzld/piaoquan/recommend/server/ctr" +
+      "_samples.proto\"E\n\014FeatureGroup\022\014\n\004type\030\001" +
+      " \001(\t\022\n\n\002id\030\002 \001(\005\022\014\n\004name\030\003 \001(\t\022\r\n\005field\030" +
+      "\004 \001(\t\"Y\n\013BaseFeature\022\n\n\002id\030\001 \001(\003\022\022\n\niden" +
+      "tifier\030\002 \001(\003\022\013\n\003fea\030\003 \001(\t\022\r\n\005value\030\004 \001(\001" +
+      "\022\016\n\006weight\030\005 \001(\001\"]\n\016GroupedFeature\022\034\n\005gr" +
+      "oup\030\001 \001(\0132\r.FeatureGroup\022\r\n\005count\030\002 \001(\005\022" +
+      "\036\n\010features\030\003 \003(\0132\014.BaseFeature\"=\n\010LRWei" +
+      "ght\022\021\n\tgroup_num\030\001 \001(\005\022\036\n\010features\030\002 \003(\013" +
+      "2\014.BaseFeature\"\207\001\n\tLRSamples\022\020\n\010is_click" +
+      "\030\001 \001(\005\022\021\n\tgroup_num\030\002 \001(\005\022\r\n\005count\030\003 \001(\005" +
+      "\022!\n\010features\030\004 \003(\0132\017.GroupedFeature\022\016\n\006w" +
+      "eight\030\005 \001(\001\022\023\n\013predict_ctr\030\006 \001(\001B7\n0com." +
+      "tzld.piaoquan.recommend.server.gen.recom" +
+      "mendP\001\210\001\001b\006proto3"
+    };
+    descriptor = com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        });
+    internal_static_FeatureGroup_descriptor =
+      getDescriptor().getMessageTypes().get(0);
+    internal_static_FeatureGroup_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_FeatureGroup_descriptor,
+        new java.lang.String[] { "Type", "Id", "Name", "Field", });
+    internal_static_BaseFeature_descriptor =
+      getDescriptor().getMessageTypes().get(1);
+    internal_static_BaseFeature_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_BaseFeature_descriptor,
+        new java.lang.String[] { "Id", "Identifier", "Fea", "Value", "Weight", });
+    internal_static_GroupedFeature_descriptor =
+      getDescriptor().getMessageTypes().get(2);
+    internal_static_GroupedFeature_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_GroupedFeature_descriptor,
+        new java.lang.String[] { "Group", "Count", "Features", });
+    internal_static_LRWeight_descriptor =
+      getDescriptor().getMessageTypes().get(3);
+    internal_static_LRWeight_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_LRWeight_descriptor,
+        new java.lang.String[] { "GroupNum", "Features", });
+    internal_static_LRSamples_descriptor =
+      getDescriptor().getMessageTypes().get(4);
+    internal_static_LRSamples_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+        internal_static_LRSamples_descriptor,
+        new java.lang.String[] { "IsClick", "GroupNum", "Count", "Features", "Weight", "PredictCtr", });
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}

+ 897 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/FeatureGroup.java

@@ -0,0 +1,897 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+/**
+ * Protobuf type {@code FeatureGroup}
+ */
+public final class FeatureGroup extends
+    com.google.protobuf.GeneratedMessageV3 implements
+    // @@protoc_insertion_point(message_implements:FeatureGroup)
+    FeatureGroupOrBuilder {
+private static final long serialVersionUID = 0L;
+  // Use FeatureGroup.newBuilder() to construct.
+  private FeatureGroup(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+  private FeatureGroup() {
+    type_ = "";
+    name_ = "";
+    field_ = "";
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(
+      UnusedPrivateParameter unused) {
+    return new FeatureGroup();
+  }
+
+  @java.lang.Override
+  public final com.google.protobuf.UnknownFieldSet
+  getUnknownFields() {
+    return this.unknownFields;
+  }
+  private FeatureGroup(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    this();
+    if (extensionRegistry == null) {
+      throw new java.lang.NullPointerException();
+    }
+    com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+        com.google.protobuf.UnknownFieldSet.newBuilder();
+    try {
+      boolean done = false;
+      while (!done) {
+        int tag = input.readTag();
+        switch (tag) {
+          case 0:
+            done = true;
+            break;
+          case 10: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            type_ = s;
+            break;
+          }
+          case 16: {
+
+            id_ = input.readInt32();
+            break;
+          }
+          case 26: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            name_ = s;
+            break;
+          }
+          case 34: {
+            java.lang.String s = input.readStringRequireUtf8();
+
+            field_ = s;
+            break;
+          }
+          default: {
+            if (!parseUnknownField(
+                input, unknownFields, extensionRegistry, tag)) {
+              done = true;
+            }
+            break;
+          }
+        }
+      }
+    } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(this);
+    } catch (java.io.IOException e) {
+      throw new com.google.protobuf.InvalidProtocolBufferException(
+          e).setUnfinishedMessage(this);
+    } finally {
+      this.unknownFields = unknownFields.build();
+      makeExtensionsImmutable();
+    }
+  }
+  public static final com.google.protobuf.Descriptors.Descriptor
+      getDescriptor() {
+    return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_FeatureGroup_descriptor;
+  }
+
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_FeatureGroup_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.class, com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.Builder.class);
+  }
+
+  public static final int TYPE_FIELD_NUMBER = 1;
+  private volatile java.lang.Object type_;
+  /**
+   * <code>string type = 1;</code>
+   * @return The type.
+   */
+  @java.lang.Override
+  public java.lang.String getType() {
+    java.lang.Object ref = type_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      type_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string type = 1;</code>
+   * @return The bytes for type.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getTypeBytes() {
+    java.lang.Object ref = type_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      type_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int ID_FIELD_NUMBER = 2;
+  private int id_;
+  /**
+   * <code>int32 id = 2;</code>
+   * @return The id.
+   */
+  @java.lang.Override
+  public int getId() {
+    return id_;
+  }
+
+  public static final int NAME_FIELD_NUMBER = 3;
+  private volatile java.lang.Object name_;
+  /**
+   * <code>string name = 3;</code>
+   * @return The name.
+   */
+  @java.lang.Override
+  public java.lang.String getName() {
+    java.lang.Object ref = name_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      name_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string name = 3;</code>
+   * @return The bytes for name.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getNameBytes() {
+    java.lang.Object ref = name_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      name_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  public static final int FIELD_FIELD_NUMBER = 4;
+  private volatile java.lang.Object field_;
+  /**
+   * <code>string field = 4;</code>
+   * @return The field.
+   */
+  @java.lang.Override
+  public java.lang.String getField() {
+    java.lang.Object ref = field_;
+    if (ref instanceof java.lang.String) {
+      return (java.lang.String) ref;
+    } else {
+      com.google.protobuf.ByteString bs = 
+          (com.google.protobuf.ByteString) ref;
+      java.lang.String s = bs.toStringUtf8();
+      field_ = s;
+      return s;
+    }
+  }
+  /**
+   * <code>string field = 4;</code>
+   * @return The bytes for field.
+   */
+  @java.lang.Override
+  public com.google.protobuf.ByteString
+      getFieldBytes() {
+    java.lang.Object ref = field_;
+    if (ref instanceof java.lang.String) {
+      com.google.protobuf.ByteString b = 
+          com.google.protobuf.ByteString.copyFromUtf8(
+              (java.lang.String) ref);
+      field_ = b;
+      return b;
+    } else {
+      return (com.google.protobuf.ByteString) ref;
+    }
+  }
+
+  private byte memoizedIsInitialized = -1;
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output)
+                      throws java.io.IOException {
+    if (!getTypeBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 1, type_);
+    }
+    if (id_ != 0) {
+      output.writeInt32(2, id_);
+    }
+    if (!getNameBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 3, name_);
+    }
+    if (!getFieldBytes().isEmpty()) {
+      com.google.protobuf.GeneratedMessageV3.writeString(output, 4, field_);
+    }
+    unknownFields.writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    if (!getTypeBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, type_);
+    }
+    if (id_ != 0) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt32Size(2, id_);
+    }
+    if (!getNameBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, name_);
+    }
+    if (!getFieldBytes().isEmpty()) {
+      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(4, field_);
+    }
+    size += unknownFields.getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+     return true;
+    }
+    if (!(obj instanceof com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup)) {
+      return super.equals(obj);
+    }
+    com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup other = (com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup) obj;
+
+    if (!getType()
+        .equals(other.getType())) return false;
+    if (getId()
+        != other.getId()) return false;
+    if (!getName()
+        .equals(other.getName())) return false;
+    if (!getField()
+        .equals(other.getField())) return false;
+    if (!unknownFields.equals(other.unknownFields)) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    hash = (37 * hash) + TYPE_FIELD_NUMBER;
+    hash = (53 * hash) + getType().hashCode();
+    hash = (37 * hash) + ID_FIELD_NUMBER;
+    hash = (53 * hash) + getId();
+    hash = (37 * hash) + NAME_FIELD_NUMBER;
+    hash = (53 * hash) + getName().hashCode();
+    hash = (37 * hash) + FIELD_FIELD_NUMBER;
+    hash = (53 * hash) + getField().hashCode();
+    hash = (29 * hash) + unknownFields.hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseFrom(
+      java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseFrom(
+      java.nio.ByteBuffer data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseFrom(
+      com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseFrom(
+      byte[] data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseDelimitedFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseFrom(
+      com.google.protobuf.CodedInputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() { return newBuilder(); }
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+  public static Builder newBuilder(com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE
+        ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(
+      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   * Protobuf type {@code FeatureGroup}
+   */
+  public static final class Builder extends
+      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+      // @@protoc_insertion_point(builder_implements:FeatureGroup)
+      com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroupOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_FeatureGroup_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_FeatureGroup_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.class, com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.Builder.class);
+    }
+
+    // Construct using com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.newBuilder()
+    private Builder() {
+      maybeForceBuilderInitialization();
+    }
+
+    private Builder(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+      maybeForceBuilderInitialization();
+    }
+    private void maybeForceBuilderInitialization() {
+      if (com.google.protobuf.GeneratedMessageV3
+              .alwaysUseFieldBuilders) {
+      }
+    }
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      type_ = "";
+
+      id_ = 0;
+
+      name_ = "";
+
+      field_ = "";
+
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor
+        getDescriptorForType() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_FeatureGroup_descriptor;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup getDefaultInstanceForType() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup build() {
+      com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup buildPartial() {
+      com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup result = new com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup(this);
+      result.type_ = type_;
+      result.id_ = id_;
+      result.name_ = name_;
+      result.field_ = field_;
+      onBuilt();
+      return result;
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.setField(field, value);
+    }
+    @java.lang.Override
+    public Builder clearField(
+        com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+    @java.lang.Override
+    public Builder clearOneof(
+        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup) {
+        return mergeFrom((com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup)other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup other) {
+      if (other == com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.getDefaultInstance()) return this;
+      if (!other.getType().isEmpty()) {
+        type_ = other.type_;
+        onChanged();
+      }
+      if (other.getId() != 0) {
+        setId(other.getId());
+      }
+      if (!other.getName().isEmpty()) {
+        name_ = other.name_;
+        onChanged();
+      }
+      if (!other.getField().isEmpty()) {
+        field_ = other.field_;
+        onChanged();
+      }
+      this.mergeUnknownFields(other.unknownFields);
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup parsedMessage = null;
+      try {
+        parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        parsedMessage = (com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup) e.getUnfinishedMessage();
+        throw e.unwrapIOException();
+      } finally {
+        if (parsedMessage != null) {
+          mergeFrom(parsedMessage);
+        }
+      }
+      return this;
+    }
+
+    private java.lang.Object type_ = "";
+    /**
+     * <code>string type = 1;</code>
+     * @return The type.
+     */
+    public java.lang.String getType() {
+      java.lang.Object ref = type_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        type_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string type = 1;</code>
+     * @return The bytes for type.
+     */
+    public com.google.protobuf.ByteString
+        getTypeBytes() {
+      java.lang.Object ref = type_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        type_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string type = 1;</code>
+     * @param value The type to set.
+     * @return This builder for chaining.
+     */
+    public Builder setType(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      type_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string type = 1;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearType() {
+      
+      type_ = getDefaultInstance().getType();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string type = 1;</code>
+     * @param value The bytes for type to set.
+     * @return This builder for chaining.
+     */
+    public Builder setTypeBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      type_ = value;
+      onChanged();
+      return this;
+    }
+
+    private int id_ ;
+    /**
+     * <code>int32 id = 2;</code>
+     * @return The id.
+     */
+    @java.lang.Override
+    public int getId() {
+      return id_;
+    }
+    /**
+     * <code>int32 id = 2;</code>
+     * @param value The id to set.
+     * @return This builder for chaining.
+     */
+    public Builder setId(int value) {
+      
+      id_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int32 id = 2;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearId() {
+      
+      id_ = 0;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object name_ = "";
+    /**
+     * <code>string name = 3;</code>
+     * @return The name.
+     */
+    public java.lang.String getName() {
+      java.lang.Object ref = name_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        name_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string name = 3;</code>
+     * @return The bytes for name.
+     */
+    public com.google.protobuf.ByteString
+        getNameBytes() {
+      java.lang.Object ref = name_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        name_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string name = 3;</code>
+     * @param value The name to set.
+     * @return This builder for chaining.
+     */
+    public Builder setName(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      name_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string name = 3;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearName() {
+      
+      name_ = getDefaultInstance().getName();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string name = 3;</code>
+     * @param value The bytes for name to set.
+     * @return This builder for chaining.
+     */
+    public Builder setNameBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      name_ = value;
+      onChanged();
+      return this;
+    }
+
+    private java.lang.Object field_ = "";
+    /**
+     * <code>string field = 4;</code>
+     * @return The field.
+     */
+    public java.lang.String getField() {
+      java.lang.Object ref = field_;
+      if (!(ref instanceof java.lang.String)) {
+        com.google.protobuf.ByteString bs =
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        field_ = s;
+        return s;
+      } else {
+        return (java.lang.String) ref;
+      }
+    }
+    /**
+     * <code>string field = 4;</code>
+     * @return The bytes for field.
+     */
+    public com.google.protobuf.ByteString
+        getFieldBytes() {
+      java.lang.Object ref = field_;
+      if (ref instanceof String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        field_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+    /**
+     * <code>string field = 4;</code>
+     * @param value The field to set.
+     * @return This builder for chaining.
+     */
+    public Builder setField(
+        java.lang.String value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  
+      field_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string field = 4;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearField() {
+      
+      field_ = getDefaultInstance().getField();
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>string field = 4;</code>
+     * @param value The bytes for field to set.
+     * @return This builder for chaining.
+     */
+    public Builder setFieldBytes(
+        com.google.protobuf.ByteString value) {
+      if (value == null) {
+    throw new NullPointerException();
+  }
+  checkByteStringIsUtf8(value);
+      
+      field_ = value;
+      onChanged();
+      return this;
+    }
+    @java.lang.Override
+    public final Builder setUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+
+    // @@protoc_insertion_point(builder_scope:FeatureGroup)
+  }
+
+  // @@protoc_insertion_point(class_scope:FeatureGroup)
+  private static final com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup DEFAULT_INSTANCE;
+  static {
+    DEFAULT_INSTANCE = new com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup();
+  }
+
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<FeatureGroup>
+      PARSER = new com.google.protobuf.AbstractParser<FeatureGroup>() {
+    @java.lang.Override
+    public FeatureGroup parsePartialFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return new FeatureGroup(input, extensionRegistry);
+    }
+  };
+
+  public static com.google.protobuf.Parser<FeatureGroup> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<FeatureGroup> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+
+}
+

+ 51 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/FeatureGroupOrBuilder.java

@@ -0,0 +1,51 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+public interface FeatureGroupOrBuilder extends
+    // @@protoc_insertion_point(interface_extends:FeatureGroup)
+    com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>string type = 1;</code>
+   * @return The type.
+   */
+  java.lang.String getType();
+  /**
+   * <code>string type = 1;</code>
+   * @return The bytes for type.
+   */
+  com.google.protobuf.ByteString
+      getTypeBytes();
+
+  /**
+   * <code>int32 id = 2;</code>
+   * @return The id.
+   */
+  int getId();
+
+  /**
+   * <code>string name = 3;</code>
+   * @return The name.
+   */
+  java.lang.String getName();
+  /**
+   * <code>string name = 3;</code>
+   * @return The bytes for name.
+   */
+  com.google.protobuf.ByteString
+      getNameBytes();
+
+  /**
+   * <code>string field = 4;</code>
+   * @return The field.
+   */
+  java.lang.String getField();
+  /**
+   * <code>string field = 4;</code>
+   * @return The bytes for field.
+   */
+  com.google.protobuf.ByteString
+      getFieldBytes();
+}

+ 1022 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/GroupedFeature.java

@@ -0,0 +1,1022 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+/**
+ * Protobuf type {@code GroupedFeature}
+ */
+public final class GroupedFeature extends
+    com.google.protobuf.GeneratedMessageV3 implements
+    // @@protoc_insertion_point(message_implements:GroupedFeature)
+    GroupedFeatureOrBuilder {
+private static final long serialVersionUID = 0L;
+  // Use GroupedFeature.newBuilder() to construct.
+  private GroupedFeature(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+  private GroupedFeature() {
+    features_ = java.util.Collections.emptyList();
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(
+      UnusedPrivateParameter unused) {
+    return new GroupedFeature();
+  }
+
+  @java.lang.Override
+  public final com.google.protobuf.UnknownFieldSet
+  getUnknownFields() {
+    return this.unknownFields;
+  }
+  private GroupedFeature(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    this();
+    if (extensionRegistry == null) {
+      throw new java.lang.NullPointerException();
+    }
+    int mutable_bitField0_ = 0;
+    com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+        com.google.protobuf.UnknownFieldSet.newBuilder();
+    try {
+      boolean done = false;
+      while (!done) {
+        int tag = input.readTag();
+        switch (tag) {
+          case 0:
+            done = true;
+            break;
+          case 10: {
+            com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.Builder subBuilder = null;
+            if (group_ != null) {
+              subBuilder = group_.toBuilder();
+            }
+            group_ = input.readMessage(com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.parser(), extensionRegistry);
+            if (subBuilder != null) {
+              subBuilder.mergeFrom(group_);
+              group_ = subBuilder.buildPartial();
+            }
+
+            break;
+          }
+          case 16: {
+
+            count_ = input.readInt32();
+            break;
+          }
+          case 26: {
+            if (!((mutable_bitField0_ & 0x00000001) != 0)) {
+              features_ = new java.util.ArrayList<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature>();
+              mutable_bitField0_ |= 0x00000001;
+            }
+            features_.add(
+                input.readMessage(com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.parser(), extensionRegistry));
+            break;
+          }
+          default: {
+            if (!parseUnknownField(
+                input, unknownFields, extensionRegistry, tag)) {
+              done = true;
+            }
+            break;
+          }
+        }
+      }
+    } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(this);
+    } catch (java.io.IOException e) {
+      throw new com.google.protobuf.InvalidProtocolBufferException(
+          e).setUnfinishedMessage(this);
+    } finally {
+      if (((mutable_bitField0_ & 0x00000001) != 0)) {
+        features_ = java.util.Collections.unmodifiableList(features_);
+      }
+      this.unknownFields = unknownFields.build();
+      makeExtensionsImmutable();
+    }
+  }
+  public static final com.google.protobuf.Descriptors.Descriptor
+      getDescriptor() {
+    return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_GroupedFeature_descriptor;
+  }
+
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_GroupedFeature_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.class, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder.class);
+  }
+
+  public static final int GROUP_FIELD_NUMBER = 1;
+  private com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup group_;
+  /**
+   * <code>.FeatureGroup group = 1;</code>
+   * @return Whether the group field is set.
+   */
+  @java.lang.Override
+  public boolean hasGroup() {
+    return group_ != null;
+  }
+  /**
+   * <code>.FeatureGroup group = 1;</code>
+   * @return The group.
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup getGroup() {
+    return group_ == null ? com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.getDefaultInstance() : group_;
+  }
+  /**
+   * <code>.FeatureGroup group = 1;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroupOrBuilder getGroupOrBuilder() {
+    return getGroup();
+  }
+
+  public static final int COUNT_FIELD_NUMBER = 2;
+  private int count_;
+  /**
+   * <code>int32 count = 2;</code>
+   * @return The count.
+   */
+  @java.lang.Override
+  public int getCount() {
+    return count_;
+  }
+
+  public static final int FEATURES_FIELD_NUMBER = 3;
+  private java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> features_;
+  /**
+   * <code>repeated .BaseFeature features = 3;</code>
+   */
+  @java.lang.Override
+  public java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> getFeaturesList() {
+    return features_;
+  }
+  /**
+   * <code>repeated .BaseFeature features = 3;</code>
+   */
+  @java.lang.Override
+  public java.util.List<? extends com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder> 
+      getFeaturesOrBuilderList() {
+    return features_;
+  }
+  /**
+   * <code>repeated .BaseFeature features = 3;</code>
+   */
+  @java.lang.Override
+  public int getFeaturesCount() {
+    return features_.size();
+  }
+  /**
+   * <code>repeated .BaseFeature features = 3;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature getFeatures(int index) {
+    return features_.get(index);
+  }
+  /**
+   * <code>repeated .BaseFeature features = 3;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder getFeaturesOrBuilder(
+      int index) {
+    return features_.get(index);
+  }
+
+  private byte memoizedIsInitialized = -1;
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output)
+                      throws java.io.IOException {
+    if (group_ != null) {
+      output.writeMessage(1, getGroup());
+    }
+    if (count_ != 0) {
+      output.writeInt32(2, count_);
+    }
+    for (int i = 0; i < features_.size(); i++) {
+      output.writeMessage(3, features_.get(i));
+    }
+    unknownFields.writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    if (group_ != null) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(1, getGroup());
+    }
+    if (count_ != 0) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt32Size(2, count_);
+    }
+    for (int i = 0; i < features_.size(); i++) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(3, features_.get(i));
+    }
+    size += unknownFields.getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+     return true;
+    }
+    if (!(obj instanceof com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature)) {
+      return super.equals(obj);
+    }
+    com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature other = (com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature) obj;
+
+    if (hasGroup() != other.hasGroup()) return false;
+    if (hasGroup()) {
+      if (!getGroup()
+          .equals(other.getGroup())) return false;
+    }
+    if (getCount()
+        != other.getCount()) return false;
+    if (!getFeaturesList()
+        .equals(other.getFeaturesList())) return false;
+    if (!unknownFields.equals(other.unknownFields)) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    if (hasGroup()) {
+      hash = (37 * hash) + GROUP_FIELD_NUMBER;
+      hash = (53 * hash) + getGroup().hashCode();
+    }
+    hash = (37 * hash) + COUNT_FIELD_NUMBER;
+    hash = (53 * hash) + getCount();
+    if (getFeaturesCount() > 0) {
+      hash = (37 * hash) + FEATURES_FIELD_NUMBER;
+      hash = (53 * hash) + getFeaturesList().hashCode();
+    }
+    hash = (29 * hash) + unknownFields.hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseFrom(
+      java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseFrom(
+      java.nio.ByteBuffer data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseFrom(
+      com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseFrom(
+      byte[] data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseDelimitedFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseFrom(
+      com.google.protobuf.CodedInputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() { return newBuilder(); }
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+  public static Builder newBuilder(com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE
+        ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(
+      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   * Protobuf type {@code GroupedFeature}
+   */
+  public static final class Builder extends
+      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+      // @@protoc_insertion_point(builder_implements:GroupedFeature)
+      com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeatureOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_GroupedFeature_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_GroupedFeature_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.class, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder.class);
+    }
+
+    // Construct using com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.newBuilder()
+    private Builder() {
+      maybeForceBuilderInitialization();
+    }
+
+    private Builder(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+      maybeForceBuilderInitialization();
+    }
+    private void maybeForceBuilderInitialization() {
+      if (com.google.protobuf.GeneratedMessageV3
+              .alwaysUseFieldBuilders) {
+        getFeaturesFieldBuilder();
+      }
+    }
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      if (groupBuilder_ == null) {
+        group_ = null;
+      } else {
+        group_ = null;
+        groupBuilder_ = null;
+      }
+      count_ = 0;
+
+      if (featuresBuilder_ == null) {
+        features_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
+      } else {
+        featuresBuilder_.clear();
+      }
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor
+        getDescriptorForType() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_GroupedFeature_descriptor;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature getDefaultInstanceForType() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature build() {
+      com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature buildPartial() {
+      com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature result = new com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature(this);
+      int from_bitField0_ = bitField0_;
+      if (groupBuilder_ == null) {
+        result.group_ = group_;
+      } else {
+        result.group_ = groupBuilder_.build();
+      }
+      result.count_ = count_;
+      if (featuresBuilder_ == null) {
+        if (((bitField0_ & 0x00000001) != 0)) {
+          features_ = java.util.Collections.unmodifiableList(features_);
+          bitField0_ = (bitField0_ & ~0x00000001);
+        }
+        result.features_ = features_;
+      } else {
+        result.features_ = featuresBuilder_.build();
+      }
+      onBuilt();
+      return result;
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.setField(field, value);
+    }
+    @java.lang.Override
+    public Builder clearField(
+        com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+    @java.lang.Override
+    public Builder clearOneof(
+        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature) {
+        return mergeFrom((com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature)other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature other) {
+      if (other == com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.getDefaultInstance()) return this;
+      if (other.hasGroup()) {
+        mergeGroup(other.getGroup());
+      }
+      if (other.getCount() != 0) {
+        setCount(other.getCount());
+      }
+      if (featuresBuilder_ == null) {
+        if (!other.features_.isEmpty()) {
+          if (features_.isEmpty()) {
+            features_ = other.features_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+          } else {
+            ensureFeaturesIsMutable();
+            features_.addAll(other.features_);
+          }
+          onChanged();
+        }
+      } else {
+        if (!other.features_.isEmpty()) {
+          if (featuresBuilder_.isEmpty()) {
+            featuresBuilder_.dispose();
+            featuresBuilder_ = null;
+            features_ = other.features_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+            featuresBuilder_ = 
+              com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+                 getFeaturesFieldBuilder() : null;
+          } else {
+            featuresBuilder_.addAllMessages(other.features_);
+          }
+        }
+      }
+      this.mergeUnknownFields(other.unknownFields);
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature parsedMessage = null;
+      try {
+        parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        parsedMessage = (com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature) e.getUnfinishedMessage();
+        throw e.unwrapIOException();
+      } finally {
+        if (parsedMessage != null) {
+          mergeFrom(parsedMessage);
+        }
+      }
+      return this;
+    }
+    private int bitField0_;
+
+    private com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup group_;
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup, com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroupOrBuilder> groupBuilder_;
+    /**
+     * <code>.FeatureGroup group = 1;</code>
+     * @return Whether the group field is set.
+     */
+    public boolean hasGroup() {
+      return groupBuilder_ != null || group_ != null;
+    }
+    /**
+     * <code>.FeatureGroup group = 1;</code>
+     * @return The group.
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup getGroup() {
+      if (groupBuilder_ == null) {
+        return group_ == null ? com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.getDefaultInstance() : group_;
+      } else {
+        return groupBuilder_.getMessage();
+      }
+    }
+    /**
+     * <code>.FeatureGroup group = 1;</code>
+     */
+    public Builder setGroup(com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup value) {
+      if (groupBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        group_ = value;
+        onChanged();
+      } else {
+        groupBuilder_.setMessage(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.FeatureGroup group = 1;</code>
+     */
+    public Builder setGroup(
+        com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.Builder builderForValue) {
+      if (groupBuilder_ == null) {
+        group_ = builderForValue.build();
+        onChanged();
+      } else {
+        groupBuilder_.setMessage(builderForValue.build());
+      }
+
+      return this;
+    }
+    /**
+     * <code>.FeatureGroup group = 1;</code>
+     */
+    public Builder mergeGroup(com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup value) {
+      if (groupBuilder_ == null) {
+        if (group_ != null) {
+          group_ =
+            com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.newBuilder(group_).mergeFrom(value).buildPartial();
+        } else {
+          group_ = value;
+        }
+        onChanged();
+      } else {
+        groupBuilder_.mergeFrom(value);
+      }
+
+      return this;
+    }
+    /**
+     * <code>.FeatureGroup group = 1;</code>
+     */
+    public Builder clearGroup() {
+      if (groupBuilder_ == null) {
+        group_ = null;
+        onChanged();
+      } else {
+        group_ = null;
+        groupBuilder_ = null;
+      }
+
+      return this;
+    }
+    /**
+     * <code>.FeatureGroup group = 1;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.Builder getGroupBuilder() {
+      
+      onChanged();
+      return getGroupFieldBuilder().getBuilder();
+    }
+    /**
+     * <code>.FeatureGroup group = 1;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroupOrBuilder getGroupOrBuilder() {
+      if (groupBuilder_ != null) {
+        return groupBuilder_.getMessageOrBuilder();
+      } else {
+        return group_ == null ?
+            com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.getDefaultInstance() : group_;
+      }
+    }
+    /**
+     * <code>.FeatureGroup group = 1;</code>
+     */
+    private com.google.protobuf.SingleFieldBuilderV3<
+        com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup, com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroupOrBuilder> 
+        getGroupFieldBuilder() {
+      if (groupBuilder_ == null) {
+        groupBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<
+            com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup, com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroupOrBuilder>(
+                getGroup(),
+                getParentForChildren(),
+                isClean());
+        group_ = null;
+      }
+      return groupBuilder_;
+    }
+
+    private int count_ ;
+    /**
+     * <code>int32 count = 2;</code>
+     * @return The count.
+     */
+    @java.lang.Override
+    public int getCount() {
+      return count_;
+    }
+    /**
+     * <code>int32 count = 2;</code>
+     * @param value The count to set.
+     * @return This builder for chaining.
+     */
+    public Builder setCount(int value) {
+      
+      count_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int32 count = 2;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearCount() {
+      
+      count_ = 0;
+      onChanged();
+      return this;
+    }
+
+    private java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> features_ =
+      java.util.Collections.emptyList();
+    private void ensureFeaturesIsMutable() {
+      if (!((bitField0_ & 0x00000001) != 0)) {
+        features_ = new java.util.ArrayList<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature>(features_);
+        bitField0_ |= 0x00000001;
+       }
+    }
+
+    private com.google.protobuf.RepeatedFieldBuilderV3<
+        com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder> featuresBuilder_;
+
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> getFeaturesList() {
+      if (featuresBuilder_ == null) {
+        return java.util.Collections.unmodifiableList(features_);
+      } else {
+        return featuresBuilder_.getMessageList();
+      }
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public int getFeaturesCount() {
+      if (featuresBuilder_ == null) {
+        return features_.size();
+      } else {
+        return featuresBuilder_.getCount();
+      }
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature getFeatures(int index) {
+      if (featuresBuilder_ == null) {
+        return features_.get(index);
+      } else {
+        return featuresBuilder_.getMessage(index);
+      }
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public Builder setFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature value) {
+      if (featuresBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureFeaturesIsMutable();
+        features_.set(index, value);
+        onChanged();
+      } else {
+        featuresBuilder_.setMessage(index, value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public Builder setFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder builderForValue) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.set(index, builderForValue.build());
+        onChanged();
+      } else {
+        featuresBuilder_.setMessage(index, builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public Builder addFeatures(com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature value) {
+      if (featuresBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureFeaturesIsMutable();
+        features_.add(value);
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public Builder addFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature value) {
+      if (featuresBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureFeaturesIsMutable();
+        features_.add(index, value);
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(index, value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public Builder addFeatures(
+        com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder builderForValue) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.add(builderForValue.build());
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public Builder addFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder builderForValue) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.add(index, builderForValue.build());
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(index, builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public Builder addAllFeatures(
+        java.lang.Iterable<? extends com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> values) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        com.google.protobuf.AbstractMessageLite.Builder.addAll(
+            values, features_);
+        onChanged();
+      } else {
+        featuresBuilder_.addAllMessages(values);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public Builder clearFeatures() {
+      if (featuresBuilder_ == null) {
+        features_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
+        onChanged();
+      } else {
+        featuresBuilder_.clear();
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public Builder removeFeatures(int index) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.remove(index);
+        onChanged();
+      } else {
+        featuresBuilder_.remove(index);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder getFeaturesBuilder(
+        int index) {
+      return getFeaturesFieldBuilder().getBuilder(index);
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder getFeaturesOrBuilder(
+        int index) {
+      if (featuresBuilder_ == null) {
+        return features_.get(index);  } else {
+        return featuresBuilder_.getMessageOrBuilder(index);
+      }
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public java.util.List<? extends com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder> 
+         getFeaturesOrBuilderList() {
+      if (featuresBuilder_ != null) {
+        return featuresBuilder_.getMessageOrBuilderList();
+      } else {
+        return java.util.Collections.unmodifiableList(features_);
+      }
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder addFeaturesBuilder() {
+      return getFeaturesFieldBuilder().addBuilder(
+          com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.getDefaultInstance());
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder addFeaturesBuilder(
+        int index) {
+      return getFeaturesFieldBuilder().addBuilder(
+          index, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.getDefaultInstance());
+    }
+    /**
+     * <code>repeated .BaseFeature features = 3;</code>
+     */
+    public java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder> 
+         getFeaturesBuilderList() {
+      return getFeaturesFieldBuilder().getBuilderList();
+    }
+    private com.google.protobuf.RepeatedFieldBuilderV3<
+        com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder> 
+        getFeaturesFieldBuilder() {
+      if (featuresBuilder_ == null) {
+        featuresBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+            com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder>(
+                features_,
+                ((bitField0_ & 0x00000001) != 0),
+                getParentForChildren(),
+                isClean());
+        features_ = null;
+      }
+      return featuresBuilder_;
+    }
+    @java.lang.Override
+    public final Builder setUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+
+    // @@protoc_insertion_point(builder_scope:GroupedFeature)
+  }
+
+  // @@protoc_insertion_point(class_scope:GroupedFeature)
+  private static final com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature DEFAULT_INSTANCE;
+  static {
+    DEFAULT_INSTANCE = new com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature();
+  }
+
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<GroupedFeature>
+      PARSER = new com.google.protobuf.AbstractParser<GroupedFeature>() {
+    @java.lang.Override
+    public GroupedFeature parsePartialFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return new GroupedFeature(input, extensionRegistry);
+    }
+  };
+
+  public static com.google.protobuf.Parser<GroupedFeature> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<GroupedFeature> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+
+}
+

+ 54 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/GroupedFeatureOrBuilder.java

@@ -0,0 +1,54 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+public interface GroupedFeatureOrBuilder extends
+    // @@protoc_insertion_point(interface_extends:GroupedFeature)
+    com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>.FeatureGroup group = 1;</code>
+   * @return Whether the group field is set.
+   */
+  boolean hasGroup();
+  /**
+   * <code>.FeatureGroup group = 1;</code>
+   * @return The group.
+   */
+  com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroup getGroup();
+  /**
+   * <code>.FeatureGroup group = 1;</code>
+   */
+  com.tzld.piaoquan.recommend.server.gen.recommend.FeatureGroupOrBuilder getGroupOrBuilder();
+
+  /**
+   * <code>int32 count = 2;</code>
+   * @return The count.
+   */
+  int getCount();
+
+  /**
+   * <code>repeated .BaseFeature features = 3;</code>
+   */
+  java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> 
+      getFeaturesList();
+  /**
+   * <code>repeated .BaseFeature features = 3;</code>
+   */
+  com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature getFeatures(int index);
+  /**
+   * <code>repeated .BaseFeature features = 3;</code>
+   */
+  int getFeaturesCount();
+  /**
+   * <code>repeated .BaseFeature features = 3;</code>
+   */
+  java.util.List<? extends com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder> 
+      getFeaturesOrBuilderList();
+  /**
+   * <code>repeated .BaseFeature features = 3;</code>
+   */
+  com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder getFeaturesOrBuilder(
+      int index);
+}

+ 1094 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/LRSamples.java

@@ -0,0 +1,1094 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+/**
+ * Protobuf type {@code LRSamples}
+ */
+public final class LRSamples extends
+    com.google.protobuf.GeneratedMessageV3 implements
+    // @@protoc_insertion_point(message_implements:LRSamples)
+    LRSamplesOrBuilder {
+private static final long serialVersionUID = 0L;
+  // Use LRSamples.newBuilder() to construct.
+  private LRSamples(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+  private LRSamples() {
+    features_ = java.util.Collections.emptyList();
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(
+      UnusedPrivateParameter unused) {
+    return new LRSamples();
+  }
+
+  @java.lang.Override
+  public final com.google.protobuf.UnknownFieldSet
+  getUnknownFields() {
+    return this.unknownFields;
+  }
+  private LRSamples(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    this();
+    if (extensionRegistry == null) {
+      throw new java.lang.NullPointerException();
+    }
+    int mutable_bitField0_ = 0;
+    com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+        com.google.protobuf.UnknownFieldSet.newBuilder();
+    try {
+      boolean done = false;
+      while (!done) {
+        int tag = input.readTag();
+        switch (tag) {
+          case 0:
+            done = true;
+            break;
+          case 8: {
+
+            isClick_ = input.readInt32();
+            break;
+          }
+          case 16: {
+
+            groupNum_ = input.readInt32();
+            break;
+          }
+          case 24: {
+
+            count_ = input.readInt32();
+            break;
+          }
+          case 34: {
+            if (!((mutable_bitField0_ & 0x00000001) != 0)) {
+              features_ = new java.util.ArrayList<com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature>();
+              mutable_bitField0_ |= 0x00000001;
+            }
+            features_.add(
+                input.readMessage(com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.parser(), extensionRegistry));
+            break;
+          }
+          case 41: {
+
+            weight_ = input.readDouble();
+            break;
+          }
+          case 49: {
+
+            predictCtr_ = input.readDouble();
+            break;
+          }
+          default: {
+            if (!parseUnknownField(
+                input, unknownFields, extensionRegistry, tag)) {
+              done = true;
+            }
+            break;
+          }
+        }
+      }
+    } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(this);
+    } catch (java.io.IOException e) {
+      throw new com.google.protobuf.InvalidProtocolBufferException(
+          e).setUnfinishedMessage(this);
+    } finally {
+      if (((mutable_bitField0_ & 0x00000001) != 0)) {
+        features_ = java.util.Collections.unmodifiableList(features_);
+      }
+      this.unknownFields = unknownFields.build();
+      makeExtensionsImmutable();
+    }
+  }
+  public static final com.google.protobuf.Descriptors.Descriptor
+      getDescriptor() {
+    return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_LRSamples_descriptor;
+  }
+
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_LRSamples_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples.class, com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples.Builder.class);
+  }
+
+  public static final int IS_CLICK_FIELD_NUMBER = 1;
+  private int isClick_;
+  /**
+   * <code>int32 is_click = 1;</code>
+   * @return The isClick.
+   */
+  @java.lang.Override
+  public int getIsClick() {
+    return isClick_;
+  }
+
+  public static final int GROUP_NUM_FIELD_NUMBER = 2;
+  private int groupNum_;
+  /**
+   * <code>int32 group_num = 2;</code>
+   * @return The groupNum.
+   */
+  @java.lang.Override
+  public int getGroupNum() {
+    return groupNum_;
+  }
+
+  public static final int COUNT_FIELD_NUMBER = 3;
+  private int count_;
+  /**
+   * <code>int32 count = 3;</code>
+   * @return The count.
+   */
+  @java.lang.Override
+  public int getCount() {
+    return count_;
+  }
+
+  public static final int FEATURES_FIELD_NUMBER = 4;
+  private java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature> features_;
+  /**
+   * <code>repeated .GroupedFeature features = 4;</code>
+   */
+  @java.lang.Override
+  public java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature> getFeaturesList() {
+    return features_;
+  }
+  /**
+   * <code>repeated .GroupedFeature features = 4;</code>
+   */
+  @java.lang.Override
+  public java.util.List<? extends com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeatureOrBuilder> 
+      getFeaturesOrBuilderList() {
+    return features_;
+  }
+  /**
+   * <code>repeated .GroupedFeature features = 4;</code>
+   */
+  @java.lang.Override
+  public int getFeaturesCount() {
+    return features_.size();
+  }
+  /**
+   * <code>repeated .GroupedFeature features = 4;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature getFeatures(int index) {
+    return features_.get(index);
+  }
+  /**
+   * <code>repeated .GroupedFeature features = 4;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeatureOrBuilder getFeaturesOrBuilder(
+      int index) {
+    return features_.get(index);
+  }
+
+  public static final int WEIGHT_FIELD_NUMBER = 5;
+  private double weight_;
+  /**
+   * <code>double weight = 5;</code>
+   * @return The weight.
+   */
+  @java.lang.Override
+  public double getWeight() {
+    return weight_;
+  }
+
+  public static final int PREDICT_CTR_FIELD_NUMBER = 6;
+  private double predictCtr_;
+  /**
+   * <code>double predict_ctr = 6;</code>
+   * @return The predictCtr.
+   */
+  @java.lang.Override
+  public double getPredictCtr() {
+    return predictCtr_;
+  }
+
+  private byte memoizedIsInitialized = -1;
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output)
+                      throws java.io.IOException {
+    if (isClick_ != 0) {
+      output.writeInt32(1, isClick_);
+    }
+    if (groupNum_ != 0) {
+      output.writeInt32(2, groupNum_);
+    }
+    if (count_ != 0) {
+      output.writeInt32(3, count_);
+    }
+    for (int i = 0; i < features_.size(); i++) {
+      output.writeMessage(4, features_.get(i));
+    }
+    if (weight_ != 0D) {
+      output.writeDouble(5, weight_);
+    }
+    if (predictCtr_ != 0D) {
+      output.writeDouble(6, predictCtr_);
+    }
+    unknownFields.writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    if (isClick_ != 0) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt32Size(1, isClick_);
+    }
+    if (groupNum_ != 0) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt32Size(2, groupNum_);
+    }
+    if (count_ != 0) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt32Size(3, count_);
+    }
+    for (int i = 0; i < features_.size(); i++) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(4, features_.get(i));
+    }
+    if (weight_ != 0D) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeDoubleSize(5, weight_);
+    }
+    if (predictCtr_ != 0D) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeDoubleSize(6, predictCtr_);
+    }
+    size += unknownFields.getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+     return true;
+    }
+    if (!(obj instanceof com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples)) {
+      return super.equals(obj);
+    }
+    com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples other = (com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples) obj;
+
+    if (getIsClick()
+        != other.getIsClick()) return false;
+    if (getGroupNum()
+        != other.getGroupNum()) return false;
+    if (getCount()
+        != other.getCount()) return false;
+    if (!getFeaturesList()
+        .equals(other.getFeaturesList())) return false;
+    if (java.lang.Double.doubleToLongBits(getWeight())
+        != java.lang.Double.doubleToLongBits(
+            other.getWeight())) return false;
+    if (java.lang.Double.doubleToLongBits(getPredictCtr())
+        != java.lang.Double.doubleToLongBits(
+            other.getPredictCtr())) return false;
+    if (!unknownFields.equals(other.unknownFields)) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    hash = (37 * hash) + IS_CLICK_FIELD_NUMBER;
+    hash = (53 * hash) + getIsClick();
+    hash = (37 * hash) + GROUP_NUM_FIELD_NUMBER;
+    hash = (53 * hash) + getGroupNum();
+    hash = (37 * hash) + COUNT_FIELD_NUMBER;
+    hash = (53 * hash) + getCount();
+    if (getFeaturesCount() > 0) {
+      hash = (37 * hash) + FEATURES_FIELD_NUMBER;
+      hash = (53 * hash) + getFeaturesList().hashCode();
+    }
+    hash = (37 * hash) + WEIGHT_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        java.lang.Double.doubleToLongBits(getWeight()));
+    hash = (37 * hash) + PREDICT_CTR_FIELD_NUMBER;
+    hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
+        java.lang.Double.doubleToLongBits(getPredictCtr()));
+    hash = (29 * hash) + unknownFields.hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseFrom(
+      java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseFrom(
+      java.nio.ByteBuffer data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseFrom(
+      com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseFrom(
+      byte[] data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseDelimitedFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseFrom(
+      com.google.protobuf.CodedInputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() { return newBuilder(); }
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+  public static Builder newBuilder(com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE
+        ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(
+      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   * Protobuf type {@code LRSamples}
+   */
+  public static final class Builder extends
+      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+      // @@protoc_insertion_point(builder_implements:LRSamples)
+      com.tzld.piaoquan.recommend.server.gen.recommend.LRSamplesOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_LRSamples_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_LRSamples_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples.class, com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples.Builder.class);
+    }
+
+    // Construct using com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples.newBuilder()
+    private Builder() {
+      maybeForceBuilderInitialization();
+    }
+
+    private Builder(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+      maybeForceBuilderInitialization();
+    }
+    private void maybeForceBuilderInitialization() {
+      if (com.google.protobuf.GeneratedMessageV3
+              .alwaysUseFieldBuilders) {
+        getFeaturesFieldBuilder();
+      }
+    }
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      isClick_ = 0;
+
+      groupNum_ = 0;
+
+      count_ = 0;
+
+      if (featuresBuilder_ == null) {
+        features_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
+      } else {
+        featuresBuilder_.clear();
+      }
+      weight_ = 0D;
+
+      predictCtr_ = 0D;
+
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor
+        getDescriptorForType() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_LRSamples_descriptor;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples getDefaultInstanceForType() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples build() {
+      com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples buildPartial() {
+      com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples result = new com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples(this);
+      int from_bitField0_ = bitField0_;
+      result.isClick_ = isClick_;
+      result.groupNum_ = groupNum_;
+      result.count_ = count_;
+      if (featuresBuilder_ == null) {
+        if (((bitField0_ & 0x00000001) != 0)) {
+          features_ = java.util.Collections.unmodifiableList(features_);
+          bitField0_ = (bitField0_ & ~0x00000001);
+        }
+        result.features_ = features_;
+      } else {
+        result.features_ = featuresBuilder_.build();
+      }
+      result.weight_ = weight_;
+      result.predictCtr_ = predictCtr_;
+      onBuilt();
+      return result;
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.setField(field, value);
+    }
+    @java.lang.Override
+    public Builder clearField(
+        com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+    @java.lang.Override
+    public Builder clearOneof(
+        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples) {
+        return mergeFrom((com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples)other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples other) {
+      if (other == com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples.getDefaultInstance()) return this;
+      if (other.getIsClick() != 0) {
+        setIsClick(other.getIsClick());
+      }
+      if (other.getGroupNum() != 0) {
+        setGroupNum(other.getGroupNum());
+      }
+      if (other.getCount() != 0) {
+        setCount(other.getCount());
+      }
+      if (featuresBuilder_ == null) {
+        if (!other.features_.isEmpty()) {
+          if (features_.isEmpty()) {
+            features_ = other.features_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+          } else {
+            ensureFeaturesIsMutable();
+            features_.addAll(other.features_);
+          }
+          onChanged();
+        }
+      } else {
+        if (!other.features_.isEmpty()) {
+          if (featuresBuilder_.isEmpty()) {
+            featuresBuilder_.dispose();
+            featuresBuilder_ = null;
+            features_ = other.features_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+            featuresBuilder_ = 
+              com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+                 getFeaturesFieldBuilder() : null;
+          } else {
+            featuresBuilder_.addAllMessages(other.features_);
+          }
+        }
+      }
+      if (other.getWeight() != 0D) {
+        setWeight(other.getWeight());
+      }
+      if (other.getPredictCtr() != 0D) {
+        setPredictCtr(other.getPredictCtr());
+      }
+      this.mergeUnknownFields(other.unknownFields);
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples parsedMessage = null;
+      try {
+        parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        parsedMessage = (com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples) e.getUnfinishedMessage();
+        throw e.unwrapIOException();
+      } finally {
+        if (parsedMessage != null) {
+          mergeFrom(parsedMessage);
+        }
+      }
+      return this;
+    }
+    private int bitField0_;
+
+    private int isClick_ ;
+    /**
+     * <code>int32 is_click = 1;</code>
+     * @return The isClick.
+     */
+    @java.lang.Override
+    public int getIsClick() {
+      return isClick_;
+    }
+    /**
+     * <code>int32 is_click = 1;</code>
+     * @param value The isClick to set.
+     * @return This builder for chaining.
+     */
+    public Builder setIsClick(int value) {
+      
+      isClick_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int32 is_click = 1;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearIsClick() {
+      
+      isClick_ = 0;
+      onChanged();
+      return this;
+    }
+
+    private int groupNum_ ;
+    /**
+     * <code>int32 group_num = 2;</code>
+     * @return The groupNum.
+     */
+    @java.lang.Override
+    public int getGroupNum() {
+      return groupNum_;
+    }
+    /**
+     * <code>int32 group_num = 2;</code>
+     * @param value The groupNum to set.
+     * @return This builder for chaining.
+     */
+    public Builder setGroupNum(int value) {
+      
+      groupNum_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int32 group_num = 2;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearGroupNum() {
+      
+      groupNum_ = 0;
+      onChanged();
+      return this;
+    }
+
+    private int count_ ;
+    /**
+     * <code>int32 count = 3;</code>
+     * @return The count.
+     */
+    @java.lang.Override
+    public int getCount() {
+      return count_;
+    }
+    /**
+     * <code>int32 count = 3;</code>
+     * @param value The count to set.
+     * @return This builder for chaining.
+     */
+    public Builder setCount(int value) {
+      
+      count_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int32 count = 3;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearCount() {
+      
+      count_ = 0;
+      onChanged();
+      return this;
+    }
+
+    private java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature> features_ =
+      java.util.Collections.emptyList();
+    private void ensureFeaturesIsMutable() {
+      if (!((bitField0_ & 0x00000001) != 0)) {
+        features_ = new java.util.ArrayList<com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature>(features_);
+        bitField0_ |= 0x00000001;
+       }
+    }
+
+    private com.google.protobuf.RepeatedFieldBuilderV3<
+        com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeatureOrBuilder> featuresBuilder_;
+
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature> getFeaturesList() {
+      if (featuresBuilder_ == null) {
+        return java.util.Collections.unmodifiableList(features_);
+      } else {
+        return featuresBuilder_.getMessageList();
+      }
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public int getFeaturesCount() {
+      if (featuresBuilder_ == null) {
+        return features_.size();
+      } else {
+        return featuresBuilder_.getCount();
+      }
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature getFeatures(int index) {
+      if (featuresBuilder_ == null) {
+        return features_.get(index);
+      } else {
+        return featuresBuilder_.getMessage(index);
+      }
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public Builder setFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature value) {
+      if (featuresBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureFeaturesIsMutable();
+        features_.set(index, value);
+        onChanged();
+      } else {
+        featuresBuilder_.setMessage(index, value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public Builder setFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder builderForValue) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.set(index, builderForValue.build());
+        onChanged();
+      } else {
+        featuresBuilder_.setMessage(index, builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public Builder addFeatures(com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature value) {
+      if (featuresBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureFeaturesIsMutable();
+        features_.add(value);
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public Builder addFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature value) {
+      if (featuresBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureFeaturesIsMutable();
+        features_.add(index, value);
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(index, value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public Builder addFeatures(
+        com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder builderForValue) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.add(builderForValue.build());
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public Builder addFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder builderForValue) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.add(index, builderForValue.build());
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(index, builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public Builder addAllFeatures(
+        java.lang.Iterable<? extends com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature> values) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        com.google.protobuf.AbstractMessageLite.Builder.addAll(
+            values, features_);
+        onChanged();
+      } else {
+        featuresBuilder_.addAllMessages(values);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public Builder clearFeatures() {
+      if (featuresBuilder_ == null) {
+        features_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
+        onChanged();
+      } else {
+        featuresBuilder_.clear();
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public Builder removeFeatures(int index) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.remove(index);
+        onChanged();
+      } else {
+        featuresBuilder_.remove(index);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder getFeaturesBuilder(
+        int index) {
+      return getFeaturesFieldBuilder().getBuilder(index);
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeatureOrBuilder getFeaturesOrBuilder(
+        int index) {
+      if (featuresBuilder_ == null) {
+        return features_.get(index);  } else {
+        return featuresBuilder_.getMessageOrBuilder(index);
+      }
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public java.util.List<? extends com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeatureOrBuilder> 
+         getFeaturesOrBuilderList() {
+      if (featuresBuilder_ != null) {
+        return featuresBuilder_.getMessageOrBuilderList();
+      } else {
+        return java.util.Collections.unmodifiableList(features_);
+      }
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder addFeaturesBuilder() {
+      return getFeaturesFieldBuilder().addBuilder(
+          com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.getDefaultInstance());
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder addFeaturesBuilder(
+        int index) {
+      return getFeaturesFieldBuilder().addBuilder(
+          index, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.getDefaultInstance());
+    }
+    /**
+     * <code>repeated .GroupedFeature features = 4;</code>
+     */
+    public java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder> 
+         getFeaturesBuilderList() {
+      return getFeaturesFieldBuilder().getBuilderList();
+    }
+    private com.google.protobuf.RepeatedFieldBuilderV3<
+        com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeatureOrBuilder> 
+        getFeaturesFieldBuilder() {
+      if (featuresBuilder_ == null) {
+        featuresBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+            com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeatureOrBuilder>(
+                features_,
+                ((bitField0_ & 0x00000001) != 0),
+                getParentForChildren(),
+                isClean());
+        features_ = null;
+      }
+      return featuresBuilder_;
+    }
+
+    private double weight_ ;
+    /**
+     * <code>double weight = 5;</code>
+     * @return The weight.
+     */
+    @java.lang.Override
+    public double getWeight() {
+      return weight_;
+    }
+    /**
+     * <code>double weight = 5;</code>
+     * @param value The weight to set.
+     * @return This builder for chaining.
+     */
+    public Builder setWeight(double value) {
+      
+      weight_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>double weight = 5;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearWeight() {
+      
+      weight_ = 0D;
+      onChanged();
+      return this;
+    }
+
+    private double predictCtr_ ;
+    /**
+     * <code>double predict_ctr = 6;</code>
+     * @return The predictCtr.
+     */
+    @java.lang.Override
+    public double getPredictCtr() {
+      return predictCtr_;
+    }
+    /**
+     * <code>double predict_ctr = 6;</code>
+     * @param value The predictCtr to set.
+     * @return This builder for chaining.
+     */
+    public Builder setPredictCtr(double value) {
+      
+      predictCtr_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>double predict_ctr = 6;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearPredictCtr() {
+      
+      predictCtr_ = 0D;
+      onChanged();
+      return this;
+    }
+    @java.lang.Override
+    public final Builder setUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+
+    // @@protoc_insertion_point(builder_scope:LRSamples)
+  }
+
+  // @@protoc_insertion_point(class_scope:LRSamples)
+  private static final com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples DEFAULT_INSTANCE;
+  static {
+    DEFAULT_INSTANCE = new com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples();
+  }
+
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<LRSamples>
+      PARSER = new com.google.protobuf.AbstractParser<LRSamples>() {
+    @java.lang.Override
+    public LRSamples parsePartialFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return new LRSamples(input, extensionRegistry);
+    }
+  };
+
+  public static com.google.protobuf.Parser<LRSamples> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<LRSamples> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+
+}
+

+ 63 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/LRSamplesOrBuilder.java

@@ -0,0 +1,63 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+public interface LRSamplesOrBuilder extends
+    // @@protoc_insertion_point(interface_extends:LRSamples)
+    com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>int32 is_click = 1;</code>
+   * @return The isClick.
+   */
+  int getIsClick();
+
+  /**
+   * <code>int32 group_num = 2;</code>
+   * @return The groupNum.
+   */
+  int getGroupNum();
+
+  /**
+   * <code>int32 count = 3;</code>
+   * @return The count.
+   */
+  int getCount();
+
+  /**
+   * <code>repeated .GroupedFeature features = 4;</code>
+   */
+  java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature> 
+      getFeaturesList();
+  /**
+   * <code>repeated .GroupedFeature features = 4;</code>
+   */
+  com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature getFeatures(int index);
+  /**
+   * <code>repeated .GroupedFeature features = 4;</code>
+   */
+  int getFeaturesCount();
+  /**
+   * <code>repeated .GroupedFeature features = 4;</code>
+   */
+  java.util.List<? extends com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeatureOrBuilder> 
+      getFeaturesOrBuilderList();
+  /**
+   * <code>repeated .GroupedFeature features = 4;</code>
+   */
+  com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeatureOrBuilder getFeaturesOrBuilder(
+      int index);
+
+  /**
+   * <code>double weight = 5;</code>
+   * @return The weight.
+   */
+  double getWeight();
+
+  /**
+   * <code>double predict_ctr = 6;</code>
+   * @return The predictCtr.
+   */
+  double getPredictCtr();
+}

+ 834 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/LRWeight.java

@@ -0,0 +1,834 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+/**
+ * Protobuf type {@code LRWeight}
+ */
+public final class LRWeight extends
+    com.google.protobuf.GeneratedMessageV3 implements
+    // @@protoc_insertion_point(message_implements:LRWeight)
+    LRWeightOrBuilder {
+private static final long serialVersionUID = 0L;
+  // Use LRWeight.newBuilder() to construct.
+  private LRWeight(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
+    super(builder);
+  }
+  private LRWeight() {
+    features_ = java.util.Collections.emptyList();
+  }
+
+  @java.lang.Override
+  @SuppressWarnings({"unused"})
+  protected java.lang.Object newInstance(
+      UnusedPrivateParameter unused) {
+    return new LRWeight();
+  }
+
+  @java.lang.Override
+  public final com.google.protobuf.UnknownFieldSet
+  getUnknownFields() {
+    return this.unknownFields;
+  }
+  private LRWeight(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    this();
+    if (extensionRegistry == null) {
+      throw new java.lang.NullPointerException();
+    }
+    int mutable_bitField0_ = 0;
+    com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+        com.google.protobuf.UnknownFieldSet.newBuilder();
+    try {
+      boolean done = false;
+      while (!done) {
+        int tag = input.readTag();
+        switch (tag) {
+          case 0:
+            done = true;
+            break;
+          case 8: {
+
+            groupNum_ = input.readInt32();
+            break;
+          }
+          case 18: {
+            if (!((mutable_bitField0_ & 0x00000001) != 0)) {
+              features_ = new java.util.ArrayList<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature>();
+              mutable_bitField0_ |= 0x00000001;
+            }
+            features_.add(
+                input.readMessage(com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.parser(), extensionRegistry));
+            break;
+          }
+          default: {
+            if (!parseUnknownField(
+                input, unknownFields, extensionRegistry, tag)) {
+              done = true;
+            }
+            break;
+          }
+        }
+      }
+    } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+      throw e.setUnfinishedMessage(this);
+    } catch (java.io.IOException e) {
+      throw new com.google.protobuf.InvalidProtocolBufferException(
+          e).setUnfinishedMessage(this);
+    } finally {
+      if (((mutable_bitField0_ & 0x00000001) != 0)) {
+        features_ = java.util.Collections.unmodifiableList(features_);
+      }
+      this.unknownFields = unknownFields.build();
+      makeExtensionsImmutable();
+    }
+  }
+  public static final com.google.protobuf.Descriptors.Descriptor
+      getDescriptor() {
+    return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_LRWeight_descriptor;
+  }
+
+  @java.lang.Override
+  protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+      internalGetFieldAccessorTable() {
+    return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_LRWeight_fieldAccessorTable
+        .ensureFieldAccessorsInitialized(
+            com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight.class, com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight.Builder.class);
+  }
+
+  public static final int GROUP_NUM_FIELD_NUMBER = 1;
+  private int groupNum_;
+  /**
+   * <code>int32 group_num = 1;</code>
+   * @return The groupNum.
+   */
+  @java.lang.Override
+  public int getGroupNum() {
+    return groupNum_;
+  }
+
+  public static final int FEATURES_FIELD_NUMBER = 2;
+  private java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> features_;
+  /**
+   * <code>repeated .BaseFeature features = 2;</code>
+   */
+  @java.lang.Override
+  public java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> getFeaturesList() {
+    return features_;
+  }
+  /**
+   * <code>repeated .BaseFeature features = 2;</code>
+   */
+  @java.lang.Override
+  public java.util.List<? extends com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder> 
+      getFeaturesOrBuilderList() {
+    return features_;
+  }
+  /**
+   * <code>repeated .BaseFeature features = 2;</code>
+   */
+  @java.lang.Override
+  public int getFeaturesCount() {
+    return features_.size();
+  }
+  /**
+   * <code>repeated .BaseFeature features = 2;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature getFeatures(int index) {
+    return features_.get(index);
+  }
+  /**
+   * <code>repeated .BaseFeature features = 2;</code>
+   */
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder getFeaturesOrBuilder(
+      int index) {
+    return features_.get(index);
+  }
+
+  private byte memoizedIsInitialized = -1;
+  @java.lang.Override
+  public final boolean isInitialized() {
+    byte isInitialized = memoizedIsInitialized;
+    if (isInitialized == 1) return true;
+    if (isInitialized == 0) return false;
+
+    memoizedIsInitialized = 1;
+    return true;
+  }
+
+  @java.lang.Override
+  public void writeTo(com.google.protobuf.CodedOutputStream output)
+                      throws java.io.IOException {
+    if (groupNum_ != 0) {
+      output.writeInt32(1, groupNum_);
+    }
+    for (int i = 0; i < features_.size(); i++) {
+      output.writeMessage(2, features_.get(i));
+    }
+    unknownFields.writeTo(output);
+  }
+
+  @java.lang.Override
+  public int getSerializedSize() {
+    int size = memoizedSize;
+    if (size != -1) return size;
+
+    size = 0;
+    if (groupNum_ != 0) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeInt32Size(1, groupNum_);
+    }
+    for (int i = 0; i < features_.size(); i++) {
+      size += com.google.protobuf.CodedOutputStream
+        .computeMessageSize(2, features_.get(i));
+    }
+    size += unknownFields.getSerializedSize();
+    memoizedSize = size;
+    return size;
+  }
+
+  @java.lang.Override
+  public boolean equals(final java.lang.Object obj) {
+    if (obj == this) {
+     return true;
+    }
+    if (!(obj instanceof com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight)) {
+      return super.equals(obj);
+    }
+    com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight other = (com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight) obj;
+
+    if (getGroupNum()
+        != other.getGroupNum()) return false;
+    if (!getFeaturesList()
+        .equals(other.getFeaturesList())) return false;
+    if (!unknownFields.equals(other.unknownFields)) return false;
+    return true;
+  }
+
+  @java.lang.Override
+  public int hashCode() {
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
+    }
+    int hash = 41;
+    hash = (19 * hash) + getDescriptor().hashCode();
+    hash = (37 * hash) + GROUP_NUM_FIELD_NUMBER;
+    hash = (53 * hash) + getGroupNum();
+    if (getFeaturesCount() > 0) {
+      hash = (37 * hash) + FEATURES_FIELD_NUMBER;
+      hash = (53 * hash) + getFeaturesList().hashCode();
+    }
+    hash = (29 * hash) + unknownFields.hashCode();
+    memoizedHashCode = hash;
+    return hash;
+  }
+
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseFrom(
+      java.nio.ByteBuffer data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseFrom(
+      java.nio.ByteBuffer data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseFrom(
+      com.google.protobuf.ByteString data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseFrom(
+      com.google.protobuf.ByteString data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseFrom(byte[] data)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseFrom(
+      byte[] data,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws com.google.protobuf.InvalidProtocolBufferException {
+    return PARSER.parseFrom(data, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseDelimitedFrom(java.io.InputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseDelimitedFrom(
+      java.io.InputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseFrom(
+      com.google.protobuf.CodedInputStream input)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input);
+  }
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parseFrom(
+      com.google.protobuf.CodedInputStream input,
+      com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+      throws java.io.IOException {
+    return com.google.protobuf.GeneratedMessageV3
+        .parseWithIOException(PARSER, input, extensionRegistry);
+  }
+
+  @java.lang.Override
+  public Builder newBuilderForType() { return newBuilder(); }
+  public static Builder newBuilder() {
+    return DEFAULT_INSTANCE.toBuilder();
+  }
+  public static Builder newBuilder(com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight prototype) {
+    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+  }
+  @java.lang.Override
+  public Builder toBuilder() {
+    return this == DEFAULT_INSTANCE
+        ? new Builder() : new Builder().mergeFrom(this);
+  }
+
+  @java.lang.Override
+  protected Builder newBuilderForType(
+      com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+    Builder builder = new Builder(parent);
+    return builder;
+  }
+  /**
+   * Protobuf type {@code LRWeight}
+   */
+  public static final class Builder extends
+      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
+      // @@protoc_insertion_point(builder_implements:LRWeight)
+      com.tzld.piaoquan.recommend.server.gen.recommend.LRWeightOrBuilder {
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_LRWeight_descriptor;
+    }
+
+    @java.lang.Override
+    protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_LRWeight_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight.class, com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight.Builder.class);
+    }
+
+    // Construct using com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight.newBuilder()
+    private Builder() {
+      maybeForceBuilderInitialization();
+    }
+
+    private Builder(
+        com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+      super(parent);
+      maybeForceBuilderInitialization();
+    }
+    private void maybeForceBuilderInitialization() {
+      if (com.google.protobuf.GeneratedMessageV3
+              .alwaysUseFieldBuilders) {
+        getFeaturesFieldBuilder();
+      }
+    }
+    @java.lang.Override
+    public Builder clear() {
+      super.clear();
+      groupNum_ = 0;
+
+      if (featuresBuilder_ == null) {
+        features_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
+      } else {
+        featuresBuilder_.clear();
+      }
+      return this;
+    }
+
+    @java.lang.Override
+    public com.google.protobuf.Descriptors.Descriptor
+        getDescriptorForType() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.CtrSamples.internal_static_LRWeight_descriptor;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight getDefaultInstanceForType() {
+      return com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight.getDefaultInstance();
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight build() {
+      com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight result = buildPartial();
+      if (!result.isInitialized()) {
+        throw newUninitializedMessageException(result);
+      }
+      return result;
+    }
+
+    @java.lang.Override
+    public com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight buildPartial() {
+      com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight result = new com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight(this);
+      int from_bitField0_ = bitField0_;
+      result.groupNum_ = groupNum_;
+      if (featuresBuilder_ == null) {
+        if (((bitField0_ & 0x00000001) != 0)) {
+          features_ = java.util.Collections.unmodifiableList(features_);
+          bitField0_ = (bitField0_ & ~0x00000001);
+        }
+        result.features_ = features_;
+      } else {
+        result.features_ = featuresBuilder_.build();
+      }
+      onBuilt();
+      return result;
+    }
+
+    @java.lang.Override
+    public Builder clone() {
+      return super.clone();
+    }
+    @java.lang.Override
+    public Builder setField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.setField(field, value);
+    }
+    @java.lang.Override
+    public Builder clearField(
+        com.google.protobuf.Descriptors.FieldDescriptor field) {
+      return super.clearField(field);
+    }
+    @java.lang.Override
+    public Builder clearOneof(
+        com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+      return super.clearOneof(oneof);
+    }
+    @java.lang.Override
+    public Builder setRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        int index, java.lang.Object value) {
+      return super.setRepeatedField(field, index, value);
+    }
+    @java.lang.Override
+    public Builder addRepeatedField(
+        com.google.protobuf.Descriptors.FieldDescriptor field,
+        java.lang.Object value) {
+      return super.addRepeatedField(field, value);
+    }
+    @java.lang.Override
+    public Builder mergeFrom(com.google.protobuf.Message other) {
+      if (other instanceof com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight) {
+        return mergeFrom((com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight)other);
+      } else {
+        super.mergeFrom(other);
+        return this;
+      }
+    }
+
+    public Builder mergeFrom(com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight other) {
+      if (other == com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight.getDefaultInstance()) return this;
+      if (other.getGroupNum() != 0) {
+        setGroupNum(other.getGroupNum());
+      }
+      if (featuresBuilder_ == null) {
+        if (!other.features_.isEmpty()) {
+          if (features_.isEmpty()) {
+            features_ = other.features_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+          } else {
+            ensureFeaturesIsMutable();
+            features_.addAll(other.features_);
+          }
+          onChanged();
+        }
+      } else {
+        if (!other.features_.isEmpty()) {
+          if (featuresBuilder_.isEmpty()) {
+            featuresBuilder_.dispose();
+            featuresBuilder_ = null;
+            features_ = other.features_;
+            bitField0_ = (bitField0_ & ~0x00000001);
+            featuresBuilder_ = 
+              com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ?
+                 getFeaturesFieldBuilder() : null;
+          } else {
+            featuresBuilder_.addAllMessages(other.features_);
+          }
+        }
+      }
+      this.mergeUnknownFields(other.unknownFields);
+      onChanged();
+      return this;
+    }
+
+    @java.lang.Override
+    public final boolean isInitialized() {
+      return true;
+    }
+
+    @java.lang.Override
+    public Builder mergeFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight parsedMessage = null;
+      try {
+        parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        parsedMessage = (com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight) e.getUnfinishedMessage();
+        throw e.unwrapIOException();
+      } finally {
+        if (parsedMessage != null) {
+          mergeFrom(parsedMessage);
+        }
+      }
+      return this;
+    }
+    private int bitField0_;
+
+    private int groupNum_ ;
+    /**
+     * <code>int32 group_num = 1;</code>
+     * @return The groupNum.
+     */
+    @java.lang.Override
+    public int getGroupNum() {
+      return groupNum_;
+    }
+    /**
+     * <code>int32 group_num = 1;</code>
+     * @param value The groupNum to set.
+     * @return This builder for chaining.
+     */
+    public Builder setGroupNum(int value) {
+      
+      groupNum_ = value;
+      onChanged();
+      return this;
+    }
+    /**
+     * <code>int32 group_num = 1;</code>
+     * @return This builder for chaining.
+     */
+    public Builder clearGroupNum() {
+      
+      groupNum_ = 0;
+      onChanged();
+      return this;
+    }
+
+    private java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> features_ =
+      java.util.Collections.emptyList();
+    private void ensureFeaturesIsMutable() {
+      if (!((bitField0_ & 0x00000001) != 0)) {
+        features_ = new java.util.ArrayList<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature>(features_);
+        bitField0_ |= 0x00000001;
+       }
+    }
+
+    private com.google.protobuf.RepeatedFieldBuilderV3<
+        com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder> featuresBuilder_;
+
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> getFeaturesList() {
+      if (featuresBuilder_ == null) {
+        return java.util.Collections.unmodifiableList(features_);
+      } else {
+        return featuresBuilder_.getMessageList();
+      }
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public int getFeaturesCount() {
+      if (featuresBuilder_ == null) {
+        return features_.size();
+      } else {
+        return featuresBuilder_.getCount();
+      }
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature getFeatures(int index) {
+      if (featuresBuilder_ == null) {
+        return features_.get(index);
+      } else {
+        return featuresBuilder_.getMessage(index);
+      }
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public Builder setFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature value) {
+      if (featuresBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureFeaturesIsMutable();
+        features_.set(index, value);
+        onChanged();
+      } else {
+        featuresBuilder_.setMessage(index, value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public Builder setFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder builderForValue) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.set(index, builderForValue.build());
+        onChanged();
+      } else {
+        featuresBuilder_.setMessage(index, builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public Builder addFeatures(com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature value) {
+      if (featuresBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureFeaturesIsMutable();
+        features_.add(value);
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public Builder addFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature value) {
+      if (featuresBuilder_ == null) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        ensureFeaturesIsMutable();
+        features_.add(index, value);
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(index, value);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public Builder addFeatures(
+        com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder builderForValue) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.add(builderForValue.build());
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public Builder addFeatures(
+        int index, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder builderForValue) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.add(index, builderForValue.build());
+        onChanged();
+      } else {
+        featuresBuilder_.addMessage(index, builderForValue.build());
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public Builder addAllFeatures(
+        java.lang.Iterable<? extends com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> values) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        com.google.protobuf.AbstractMessageLite.Builder.addAll(
+            values, features_);
+        onChanged();
+      } else {
+        featuresBuilder_.addAllMessages(values);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public Builder clearFeatures() {
+      if (featuresBuilder_ == null) {
+        features_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000001);
+        onChanged();
+      } else {
+        featuresBuilder_.clear();
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public Builder removeFeatures(int index) {
+      if (featuresBuilder_ == null) {
+        ensureFeaturesIsMutable();
+        features_.remove(index);
+        onChanged();
+      } else {
+        featuresBuilder_.remove(index);
+      }
+      return this;
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder getFeaturesBuilder(
+        int index) {
+      return getFeaturesFieldBuilder().getBuilder(index);
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder getFeaturesOrBuilder(
+        int index) {
+      if (featuresBuilder_ == null) {
+        return features_.get(index);  } else {
+        return featuresBuilder_.getMessageOrBuilder(index);
+      }
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public java.util.List<? extends com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder> 
+         getFeaturesOrBuilderList() {
+      if (featuresBuilder_ != null) {
+        return featuresBuilder_.getMessageOrBuilderList();
+      } else {
+        return java.util.Collections.unmodifiableList(features_);
+      }
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder addFeaturesBuilder() {
+      return getFeaturesFieldBuilder().addBuilder(
+          com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.getDefaultInstance());
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder addFeaturesBuilder(
+        int index) {
+      return getFeaturesFieldBuilder().addBuilder(
+          index, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.getDefaultInstance());
+    }
+    /**
+     * <code>repeated .BaseFeature features = 2;</code>
+     */
+    public java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder> 
+         getFeaturesBuilderList() {
+      return getFeaturesFieldBuilder().getBuilderList();
+    }
+    private com.google.protobuf.RepeatedFieldBuilderV3<
+        com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder> 
+        getFeaturesFieldBuilder() {
+      if (featuresBuilder_ == null) {
+        featuresBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3<
+            com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature.Builder, com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder>(
+                features_,
+                ((bitField0_ & 0x00000001) != 0),
+                getParentForChildren(),
+                isClean());
+        features_ = null;
+      }
+      return featuresBuilder_;
+    }
+    @java.lang.Override
+    public final Builder setUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.setUnknownFields(unknownFields);
+    }
+
+    @java.lang.Override
+    public final Builder mergeUnknownFields(
+        final com.google.protobuf.UnknownFieldSet unknownFields) {
+      return super.mergeUnknownFields(unknownFields);
+    }
+
+
+    // @@protoc_insertion_point(builder_scope:LRWeight)
+  }
+
+  // @@protoc_insertion_point(class_scope:LRWeight)
+  private static final com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight DEFAULT_INSTANCE;
+  static {
+    DEFAULT_INSTANCE = new com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight();
+  }
+
+  public static com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight getDefaultInstance() {
+    return DEFAULT_INSTANCE;
+  }
+
+  private static final com.google.protobuf.Parser<LRWeight>
+      PARSER = new com.google.protobuf.AbstractParser<LRWeight>() {
+    @java.lang.Override
+    public LRWeight parsePartialFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return new LRWeight(input, extensionRegistry);
+    }
+  };
+
+  public static com.google.protobuf.Parser<LRWeight> parser() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.google.protobuf.Parser<LRWeight> getParserForType() {
+    return PARSER;
+  }
+
+  @java.lang.Override
+  public com.tzld.piaoquan.recommend.server.gen.recommend.LRWeight getDefaultInstanceForType() {
+    return DEFAULT_INSTANCE;
+  }
+
+}
+

+ 39 - 0
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/LRWeightOrBuilder.java

@@ -0,0 +1,39 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: com/tzld/piaoquan/recommend/server/ctr_samples.proto
+
+package com.tzld.piaoquan.recommend.server.gen.recommend;
+
+public interface LRWeightOrBuilder extends
+    // @@protoc_insertion_point(interface_extends:LRWeight)
+    com.google.protobuf.MessageOrBuilder {
+
+  /**
+   * <code>int32 group_num = 1;</code>
+   * @return The groupNum.
+   */
+  int getGroupNum();
+
+  /**
+   * <code>repeated .BaseFeature features = 2;</code>
+   */
+  java.util.List<com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature> 
+      getFeaturesList();
+  /**
+   * <code>repeated .BaseFeature features = 2;</code>
+   */
+  com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature getFeatures(int index);
+  /**
+   * <code>repeated .BaseFeature features = 2;</code>
+   */
+  int getFeaturesCount();
+  /**
+   * <code>repeated .BaseFeature features = 2;</code>
+   */
+  java.util.List<? extends com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder> 
+      getFeaturesOrBuilderList();
+  /**
+   * <code>repeated .BaseFeature features = 2;</code>
+   */
+  com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeatureOrBuilder getFeaturesOrBuilder(
+      int index);
+}

+ 15 - 10
recommend-server-service/pom.xml

@@ -39,15 +39,20 @@
             <version>1.2.1</version>
         </dependency>
         <dependency>
-            <groupId>org.apache.hadoop</groupId>
-            <artifactId>hadoop-hdfs</artifactId>
-            <version>3.3.1</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.hadoop</groupId>
-            <artifactId>hadoop-common</artifactId>
-            <version>3.3.1</version>
-        </dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>3.15.1</version>
+        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.apache.hadoop</groupId>-->
+<!--            <artifactId>hadoop-hdfs</artifactId>-->
+<!--            <version>3.3.1</version>-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>org.apache.hadoop</groupId>-->
+<!--            <artifactId>hadoop-common</artifactId>-->
+<!--            <version>3.3.1</version>-->
+<!--        </dependency>-->
         <dependency>
             <groupId>it.unimi.dsi</groupId>
             <artifactId>fastutil</artifactId>
@@ -122,7 +127,7 @@
         <dependency>
             <groupId>com.tzld.piaoquan</groupId>
             <artifactId>recommend-server-client</artifactId>
-            <version>1.0.0</version>
+            <version>1.0.1</version>
         </dependency>
         <dependency>
             <groupId>com.tzld.piaoquan</groupId>

+ 1 - 15
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/VlogShareLRScorer.java

@@ -200,18 +200,4 @@ public class VlogShareLRScorer extends BaseLRModelScorer{
         }
         LOGGER.debug("Ctr Score {}, Total: {}, Cancel: {}", new Object[]{requestContext.getRequest_id(), items.size(), cancel});
     }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-}
+}

+ 0 - 5
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/GBDTModel.java

@@ -122,11 +122,6 @@ public class GBDTModel extends Model {
         }
     }
 
-    @Override
-    public boolean loadPartitions(String modelPath, boolean isRegister) {
-        return false;
-    }
-
     private float score(final Map<Integer, Node> tree, final boolean[] featureIsExists, final Float[] featureValues) {
         int id = 0;
         while (true) {

+ 7 - 259
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/LRModel.java

@@ -1,21 +1,10 @@
 package com.tzld.piaoquan.recommend.server.service.score.model;
 
-import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
-
+import com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature;
+import com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature;
+import com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples;
 import it.unimi.dsi.fastutil.longs.Long2FloatMap;
 import it.unimi.dsi.fastutil.longs.Long2FloatOpenHashMap;
-import com.tzld.piaoquan.recommend.server.gen.recommend.LRSamples;
-import com.tzld.piaoquan.recommend.server.gen.recommend.GroupedFeature;
-import com.tzld.piaoquan.recommend.server.gen.recommend.BaseFeature;
-
-import org.apache.commons.lang.exception.ExceptionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -26,30 +15,16 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
 
 
 public class LRModel extends Model {
     protected static final int MODEL_FIRST_LOAD_COUNT = 1 << 25; // 32M
     private static final Logger LOGGER = LoggerFactory.getLogger(LRModel.class);
-    private static final ExecutorService executorService = Executors.newCachedThreadPool();
     private final int bucketBits = 10;  // power(2, 10) => 1024 个槽位
     private List<Long2FloatMap> lrModel;
-    private Config config = ConfigFactory.load("hdfs_conf.properties");
-    private Configuration hdfsConf = new Configuration();
 
     public LRModel() {
         //配置不同环境的hdfs conf
-        String coreSiteFile = config.hasPath("hdfs.coreSiteFile") ? StringUtils.trim(config.getString("hdfs.coreSiteFile")) : "core-site.xml";
-        String hdfsSiteFile = config.hasPath("hdfs.hdfsSiteFile") ? StringUtils.trim(config.getString("hdfs.hdfsSiteFile")) : "hdfs-site.xml";
-        hdfsConf.addResource(coreSiteFile);
-        hdfsConf.addResource(hdfsSiteFile);
         this.lrModel = constructModel();
     }
 
@@ -97,11 +72,10 @@ public class LRModel extends Model {
 
     public Float score(LRSamples lrSamples) {
         float sum = 0.0f;
-        for(int i=0; i< lrSamples.getFeaturesCount(); i++)
-        {
+        for (int i = 0; i < lrSamples.getFeaturesCount(); i++) {
             GroupedFeature gf = lrSamples.getFeatures(i);
             if (gf != null && gf.getFeatures(i) != null) {
-                for(int j=0; j < gf.getFeaturesCount(); j++) {
+                for (int j = 0; j < gf.getFeaturesCount(); j++) {
                     BaseFeature fea = gf.getFeatures(j);
                     if (fea != null) {
                         float tmp = getWeight(this.lrModel, fea.getIdentifier());
@@ -121,11 +95,10 @@ public class LRModel extends Model {
     public Float getWeights(LRSamples lrSamples) {
         float sum = 0.0f;
 
-        for(int i=0; i< lrSamples.getFeaturesCount(); i++)
-        {
+        for (int i = 0; i < lrSamples.getFeaturesCount(); i++) {
             GroupedFeature gf = lrSamples.getFeatures(i);
             if (gf != null && gf.getFeatures(i) != null) {
-                for(int j=0; j < gf.getFeaturesCount(); j++) {
+                for (int j = 0; j < gf.getFeaturesCount(); j++) {
                     BaseFeature fea = gf.getFeatures(j);
                     if (fea != null) {
                         float tmp = getWeight(this.lrModel, fea.getIdentifier());
@@ -193,229 +166,4 @@ public class LRModel extends Model {
         return true;
     }
 
-    @Override
-    public boolean loadPartitions(final String modelPath, boolean isRegister) {
-        if (isRegister) {
-            return loadPartitionsParallel(modelPath);
-        } else {
-            return loadPartitionsSingle(modelPath);
-        }
-    }
-
-    /**
-     * 程序运行的过程中, model 太大, 为了尽可能防止full gc, 单线程加载
-     *
-     * @param modelPath
-     * @return
-     */
-
-    public boolean loadPartitionsSingle(final String modelPath) {
-        try {
-            Path path = new Path(modelPath);
-            hdfsConf.setBoolean("fs.hdfs.impl.disable.cache", true);
-
-            FileSystem fs = path.getFileSystem(hdfsConf);
-            FileStatus[] listStatus = fs.listStatus(path);
-
-            //judge null and empty
-            if (listStatus == null || listStatus.length == 0) {
-                LOGGER.error("model path is dir, but hdfs patition path is null");
-                return false;
-            }
-
-            long startTime = System.currentTimeMillis();
-
-            // 初始化model大小,直接分配到old heap
-            List<Long2FloatMap> currLrModel = constructModel();
-
-            //multi thread load hdfs news info files
-            int failedPartitionNum = 0;
-            int partitionsNum = listStatus.length;
-            for (final FileStatus file : listStatus) {
-                String absPath = String.format("%s/%s", modelPath, file.getPath().getName());
-                InputStreamReader fin = null;
-                try {
-                    Path tmpPath = new Path(absPath);
-                    FileSystem tmpFs = tmpPath.getFileSystem(hdfsConf);
-                    FSDataInputStream inputStream = tmpFs.open(tmpPath);
-                    fin = new InputStreamReader(inputStream);
-
-                    BufferedReader input = new BufferedReader(fin);
-                    String line = null;
-                    int cnt = 0;
-
-                    //first stage
-                    while ((line = input.readLine()) != null) {
-
-                        String[] items = line.split("\t");
-                        if (items.length < 2) {
-                            continue;
-                        }
-
-                        // write sync
-                        putFeature(currLrModel, new BigInteger(items[0]).longValue(), Float.valueOf(items[1]).floatValue());
-                        cnt++;
-                    }
-                    LOGGER.info("load model [SUCCESS] , file path [{}], load item number [{}]", absPath, cnt);
-                } catch (Exception e) {
-                    failedPartitionNum++;
-                    LOGGER.error("load model file from hdfs occur error [FAILED], path: [{}], [{}]",
-                            absPath, ExceptionUtils.getFullStackTrace(e));
-                } finally {
-                    if (fin != null) {
-                        try {
-                            fin.close();
-                        } catch (IOException e) {
-                            LOGGER.error("close [{}] fail: [{}]", absPath, ExceptionUtils.getFullStackTrace(e));
-                        }
-                    }
-                }
-            }
-
-            if (failedPartitionNum == 0) {
-                this.lrModel = currLrModel;
-                LOGGER.info("[end] load model data from hdfs, spend time: [{}ms] model size: [{}], " +
-                        "total partition number [{}], failed partition numbers: [{}], model path [{}]", new Object[]{
-                        (System.currentTimeMillis() - startTime), getModelSize(), partitionsNum, failedPartitionNum, modelPath});
-                return true;
-            } else {
-                LOGGER.error("load model failed parts [{}]", failedPartitionNum);
-                return false;
-            }
-        } catch (Exception e) {
-            LOGGER.error("load model partitions occur error, model path [{}], error: [{}]",
-                    modelPath, ExceptionUtils.getFullStackTrace(e));
-            return false;
-        }
-    }
-
-    /**
-     * concurrency load model from modelpath
-     * put map must be sync
-     * if partitions not 0 && load success: return true
-     * exceptions || 0 partitions || any partitions failed : return false
-     *
-     * @param modelPath
-     * @return
-     */
-    public boolean loadPartitionsParallel(final String modelPath) {
-        try {
-            Path path = new Path(modelPath);
-            FileSystem fs = path.getFileSystem(hdfsConf);
-            FileStatus[] listStatus = fs.listStatus(path);
-
-            //judge null and empty
-            if (listStatus == null || listStatus.length == 0) {
-                LOGGER.error("model path is dir, but hdfs patition path is null");
-                return false;
-            }
-
-            long startTime = System.currentTimeMillis();
-            List<Callable<Long2FloatMap>> callables = new ArrayList<Callable<Long2FloatMap>>();
-            //multi thread load hdfs news info files
-            for (final FileStatus file : listStatus) {
-                callables.add(new Callable<Long2FloatMap>() {
-                    @Override
-                    public Long2FloatMap call() {
-                        // LOGGER.debug("load model file path [{}]", file.getPath().getName());
-                        String abspath = String.format("%s/%s", modelPath, file.getPath().getName());
-                        InputStreamReader fin = null;
-                        Long2FloatMap partModel = new Long2FloatOpenHashMap();
-                        try {
-
-                            Path path = new Path(abspath);
-                            FileSystem fs = path.getFileSystem(hdfsConf);
-                            FSDataInputStream inputStream = fs.open(path);
-                            fin = new InputStreamReader(inputStream);
-
-                            BufferedReader input = new BufferedReader(fin);
-                            String line = null;
-                            int cnt = 0;
-
-                            //first stage
-                            while ((line = input.readLine()) != null) {
-
-                                String[] items = line.split("\t");
-                                if (items.length < 2) {
-                                    continue;
-                                }
-
-                                // write sync
-                                partModel.put(new BigInteger(items[0]).longValue(), Float.valueOf(items[1]).floatValue());
-                                cnt++;
-                            }
-                            LOGGER.info("load model [SUCCESS] , file path [{}], load item number [{}]", abspath, cnt);
-                            return partModel;
-                        } catch (Exception e) {
-                            LOGGER.error("load model file from hdfs occur error [FAILED], path: [{}], [{}]",
-                                    abspath, ExceptionUtils.getFullStackTrace(e));
-                            return null;
-                        } finally {
-                            if (fin != null) {
-                                try {
-                                    fin.close();
-                                } catch (IOException e) {
-                                    LOGGER.error("close [{}] fail: [{}]", abspath, ExceptionUtils.getFullStackTrace(e));
-                                    return null;
-                                }
-                            }
-                            return partModel;
-                        }
-                    }
-                });
-            }
-
-            //invoke callable if failed return
-            List<Future<Long2FloatMap>> futures = null;
-            try {
-                futures = executorService.invokeAll(callables, 10, TimeUnit.MINUTES);
-            } catch (InterruptedException e) {
-                LOGGER.error("execute invoke fail: {}", ExceptionUtils.getFullStackTrace(e));
-            }
-
-            //wait for task complete
-            int failedPartitionNum = 0;
-            int partitionsNum = listStatus.length;
-            List<Long2FloatMap> currLrModel = constructModel();
-            for (Future<Long2FloatMap> future : futures) {
-                try {
-                    if (future.isDone() && !future.isCancelled()) {
-
-                        Long2FloatMap ret = future.get();
-                        if (ret == null) {
-                            failedPartitionNum++;
-                        }
-                        for (Map.Entry<Long, Float> entry : ret.entrySet()) {
-                            putFeature(currLrModel, entry.getKey(), entry.getValue());
-                        }
-                        ret = null; // gc
-                        continue;
-                    }
-                } catch (InterruptedException e) {
-                    failedPartitionNum++;
-                    LOGGER.error("InterruptedException {},{}", ExceptionUtils.getFullStackTrace(e));
-                } catch (ExecutionException e) {
-                    failedPartitionNum++;
-                    LOGGER.error("ExecutionException [{}]", ExceptionUtils.getFullStackTrace(e));
-                }
-            }
-
-            long endTime = System.currentTimeMillis();
-            // check all load success
-            if (failedPartitionNum == 0) {
-                this.lrModel = currLrModel;
-                // counter for alarm
-                LOGGER.info("[end] load model data from hdfs, spend time: [{}ms] model size: [{}], " +
-                        "total partition number [{}], failed partition numbers: [{}], model path [{}]", new Object[]{
-                        (endTime - startTime), getModelSize(), partitionsNum, failedPartitionNum, modelPath});
-                return true;
-            }
-
-            return false;
-        } catch (Exception e) {
-            LOGGER.error("load model partitions occur error, model path [{}], error: [{}]",
-                    modelPath, ExceptionUtils.getFullStackTrace(e));
-            return false;
-        }
-    }
 }

+ 0 - 2
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/Model.java

@@ -7,7 +7,5 @@ abstract public class Model {
     public abstract int getModelSize();
 
     public abstract boolean loadFromStream(InputStreamReader in) throws Exception;
-
-    public abstract boolean loadPartitions(String modelPath, boolean isRegister);
 }
 

+ 40 - 96
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/ModelManager.java

@@ -1,45 +1,43 @@
 package com.tzld.piaoquan.recommend.server.service.score.model;
 
 
-import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
-import org.apache.commons.lang.exception.ExceptionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.common.auth.CredentialsProvider;
+import com.aliyun.oss.common.auth.DefaultCredentialProvider;
+import com.aliyun.oss.model.OSSObject;
+import lombok.extern.slf4j.Slf4j;
 
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
 
-
+@Slf4j
 public class ModelManager {
     private static final int SCHEDULE_PERIOD = 10;
-    private static final Logger LOGGER = LoggerFactory.getLogger(ModelManager.class);
     private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
     private static final String SUCCESS = "_SUCCESS";
     private static ModelManager instance;
     Map<String, ModelLoadTask> loadTasks = new HashMap<String, ModelLoadTask>();
     Map<String, String> modelPathMap = new HashMap<String, String>();
-    private Config config = ConfigFactory.load("hdfs_conf.properties");
-    private Configuration hdfsConf = new Configuration();
+    private OSS client;
+    private String bucketName;
 
     private ModelManager() {
-        //配置不同环境的hdfs conf
-        String coreSiteFile = config.hasPath("hdfs.coreSiteFile") ? StringUtils.trim(config.getString("hdfs.coreSiteFile")) : "core-site.xml";
-        String hdfsSiteFile = config.hasPath("hdfs.hdfsSiteFile") ? StringUtils.trim(config.getString("hdfs.hdfsSiteFile")) : "hdfs-site.xml";
-        hdfsConf.addResource(coreSiteFile);
-        hdfsConf.addResource(hdfsSiteFile);
+        // TODO config load
+        OssConfig config = null;
+        // oss client
+        CredentialsProvider credentialsProvider = new DefaultCredentialProvider(config.getAccessKeyId(), config.getAccessKeySecret());
+        client = new OSSClientBuilder().build(config.getEndpoint(), credentialsProvider);
+
+        this.bucketName = config.getBucketName();
 
         start(SCHEDULE_PERIOD);
     }
@@ -59,7 +57,7 @@ public class ModelManager {
      * 添加一个加载任务到管理器
      *
      * @param modelName  Model的名字, 注册到ModelManager的不同model需要不同的名字
-     * @param path       Model在HDFS上的路径
+     * @param path       Model在OSS上的全路径
      * @param modelClass Model的子类型
      */
     public void registerModel(String modelName, String path, Class<? extends Model> modelClass) throws ModelRegisterException, IOException {
@@ -67,7 +65,7 @@ public class ModelManager {
             String oldPath = modelPathMap.get(modelName);
             if (path.equals(oldPath)) {
                 //如果模型的path没有发生改变, 不做任何操作
-                LOGGER.info("Model [{}] and Path [{}] has exist", modelName, path);
+                log.info("Model [{}] and Path [{}] has exist", modelName, path);
                 return;
             } else {
                 //如果模型的path发生改变, 需要注销掉原有的任务
@@ -128,8 +126,8 @@ public class ModelManager {
             public void run() {
                 // 模型更新开关
                 // boolean modelUpdateSwitch = Configuration.getBoolean("recommend-service-framework.model-update-switch", true);
-                boolean modelUpdateSwitch =  true;
-                LOGGER.info("model update switch [{}]", modelUpdateSwitch);
+                boolean modelUpdateSwitch = true;
+                log.info("model update switch [{}]", modelUpdateSwitch);
                 if (modelUpdateSwitch) {
                     updateModels(false);
                 }
@@ -142,9 +140,9 @@ public class ModelManager {
      * 更新模型
      */
     public void updateModels(final boolean isForceLoads) {
-        LOGGER.info("begin to update: [{}]", loadTasks.keySet().size());
+        log.info("begin to update: [{}]", loadTasks.keySet().size());
         for (String modelPath : loadTasks.keySet()) {
-            LOGGER.debug("loadtask model path [{}]", modelPath);
+            log.debug("loadtask model path [{}]", modelPath);
             ModelLoadTask task = loadTasks.get(modelPath);
             loadModel(task, isForceLoads, false);
         }
@@ -152,6 +150,9 @@ public class ModelManager {
 
     /**
      * 检查并加载模型
+     * <p>
+     * 从oss加载:
+     * https://help.aliyun.com/zh/oss/developer-reference/streaming-download-7?spm=a2c4g.11186623.0.0.4b527c7dm8LejC
      *
      * @param loadTask
      */
@@ -159,87 +160,30 @@ public class ModelManager {
         if (loadTask.isLoading) {
             return;
         }
-        FSDataInputStream fin = null;
+        loadTask.isLoading = true;
+        OSSObject ossObj = null;
         try {
-            loadTask.isLoading = true;
-            Path path = new Path(loadTask.path);
-            hdfsConf.setBoolean("fs.hdfs.impl.disable.cache", true);
-
-            //根据path选择相应的filesystem
-            FileSystem fs = path.getFileSystem(hdfsConf);
-            FileStatus fileStatus = fs.getFileStatus(path);
-
-            // model is file, modify sign is file ModificationTime
-            if (fileStatus.isFile()) {
+            ossObj = client.getObject(bucketName, loadTask.path);
+            long timeStamp = ossObj.getObjectMetadata().getLastModified().getTime();
+            if (loadTask.lastModifyTime != timeStamp || isForceLoads) {
+                log.info("model file changed, ready to update, last modify: [{}]", loadTask.lastModifyTime);
 
-                long timeStamp = fileStatus.getModificationTime();
-                LOGGER.debug("model [{}] last update time: [{}]", loadTask.path, loadTask.lastModifyTime + ":" + timeStamp);
-                if (loadTask.lastModifyTime != timeStamp || isForceLoads) {
-                    LOGGER.info("find model [{}] file changed, ready to update, last modify: [{}]", loadTask.path, loadTask.lastModifyTime);
-
-                    Path modelFile = new Path(loadTask.path);
-                    fin = fs.open(modelFile);
-                    Model model = loadTask.modelClass.newInstance();
-                    if (model.loadFromStream(new InputStreamReader(fin))) {
-                        loadTask.model = model;
-                        loadTask.lastModifyTime = timeStamp;
-                        //LOGGER.info("finish load model: [{}], [{}]", loadTask.path);
-                        LOGGER.info("update model: [{}], [{}]", loadTask.path, loadTask.lastModifyTime);
-                    } else {
-                        LOGGER.error("load model fail: [{}]", loadTask.path);
-                    }
-                }
-                return;
-            }
-
-            // model is dir, modify sign is file _SUCCESS file ModificationTime
-            if (fileStatus.isDirectory()) {
-
-                String successFilePath = String.format("%s/%s", loadTask.path, SUCCESS);
-                Path successPath = new Path(successFilePath);
-                long currSuccFileModifyTime = 0;
-                if (!isForceLoads) {
-                    try {
-                        FileSystem fsSucc = successPath.getFileSystem(hdfsConf);
-                        FileStatus fileStatusSucc = fsSucc.getFileStatus(successPath);
-                        currSuccFileModifyTime = fileStatusSucc.getModificationTime();
-
-                        //check model whether update
-                        if (loadTask.lastModifyTime == currSuccFileModifyTime) {
-                            LOGGER.info("[INFO MESSAGE] _SUCCESS modifytime is not changed, last update time [{}]," +
-                                    "current modify time [{}], model path: [{}]", new Object[]{loadTask.lastModifyTime,
-                                    currSuccFileModifyTime, loadTask.path});
-                            return;
-                        }
-                    } catch (Exception e) {
-                        LOGGER.error("check _SUCCESS update time occur error, _SUCCESS path [{}], Exception: [{}]",
-                                successPath, ExceptionUtils.getFullStackTrace(e));
-                        return;
-                    }
-                }
-
-                // success has modify, multi thread load model
                 Model model = loadTask.modelClass.newInstance();
-                if (model.loadPartitions(loadTask.path, isRegister)) {
+                if (model.loadFromStream(new InputStreamReader(ossObj.getObjectContent()))) {
                     loadTask.model = model;
-                    loadTask.lastModifyTime = currSuccFileModifyTime;
-
-                    LOGGER.info("[SUCCESS] model load, update time [{}], model size [{}], model path [{}]",
-                            new Object[]{loadTask.lastModifyTime, model.getModelSize(), loadTask.path});
-                } else {
-                    LOGGER.error("load model [failed], model path [{}]", loadTask.path);
+                    loadTask.lastModifyTime = timeStamp;
                 }
             }
-
+            ossObj.close();
         } catch (Exception e) {
-            LOGGER.error("update model fail:[{}], [{}]", loadTask.path, ExceptionUtils.getFullStackTrace(e));
+            log.error("update model fail", e);
         } finally {
             loadTask.isLoading = false;
-            if (fin != null) {
+            if (ossObj != null) {
                 try {
-                    fin.close();
+                    ossObj.close();
                 } catch (IOException e) {
-                    LOGGER.error("close [{}] fail: [{}]", loadTask.path, ExceptionUtils.getFullStackTrace(e));
+                    log.error("close ossObj fail", e);
                 }
             }
         }

+ 15 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/score/model/OssConfig.java

@@ -0,0 +1,15 @@
+package com.tzld.piaoquan.recommend.server.service.score.model;
+
+import lombok.Data;
+
+/**
+ * @author dyp
+ */
+@Data
+public class OssConfig {
+
+    private String accessKeyId;
+    private String accessKeySecret;
+    private String endpoint;
+    private String bucketName;
+}