暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

编写云服务计费系统

    上一篇介绍了自建一个Laxcus云服务需要了解的基础知识,这一篇咱们从编程角度,来说说如何编写一个简单的云服务计费系统,如果你有更复杂的需求,可以在这个上面扩展。更进一步,如果你非常熟悉Laxcus分布式操作系统的运行流程,那么可以去GitHub拿源代码修改,甚至直接操作底层或者硬件获取必要信息,这样会更贴近你的需求。

闲话不多说,咱们正式进入主题。

编写一个简单的Laxcus云服务计费系统,需要这样三步:

1.了解Check User Cost命令。

2.了解Check User Cost命令的返回结果。

3.生成Check User Cost命令,调用系统DSDK软件包的API,把命令投递到Laxcus计算机集群上执行,然后等待返回结果,解析结果中的信息,结合你的计费算法,得出计费结果。


目前Laxcus分布式操作系统的DSDK软件包,只支持Java编程,同类型的C、C++接口、Python接口,还处于Alpha状态,暂时没有公布出来。所以咱们这篇文章就以Java编程的方式,来介绍编写Laxcus云服务计费的系统。


一、Check User Cost命令,源代码如下。

    public class CheckUserCost extends Command {


    private static final long serialVersionUID = 7448735013509223442L;


    /** 全部节点,这个参数只在WATCH节点有效,不做可类化 **/
    private boolean all;


    /** 节点类型 **/
    private ArrayList<java.lang.Byte> types = new ArrayList<java.lang.Byte>();


    /** 被查询的用户签名 **/
    private ArrayList<Siger> users = new ArrayList<Siger>();


    /** 用户明文。不做可类化处理,不在网络间传输 **/
    protected TreeSet<Naming> texts = new TreeSet<Naming>();


    /** 查询的命名 **/
    private TreeSet<Naming> includes = new TreeSet<Naming>();

    /** 忽略的命名 **/
    private TreeSet<Naming> excludes = new TreeSet<Naming>();


    /** 开始/结束时间 **/
    private long beginTime, endTime;


    /**
    * 构造诊断用户消耗的资源
    */
    public CheckUserCost() {
    super();
    all = false;
    }


    /**
    * 生成诊断用户消耗的资源副本
    * @param that 诊断用户消耗的资源
    */
    private CheckUserCost(CheckUserCost that) {
    super(that);
    all = that.all;
    types.addAll( that.types);
    users.addAll(that.users);
    includes.addAll(that.includes);
    excludes.addAll(that.excludes);
    beginTime = that.beginTime;
    endTime = that.endTime;
    }


    /**
    * 从可类化读取器中解析诊断用户消耗的资源
    * @param reader 可类化读取器
    */
    public CheckUserCost(ClassReader reader) {
    this();
    resolve(reader);
    }

    /**
    * 全部节点有效或者否
    * @param b 真或者假
    */
    public void setAll(boolean b) {
    all = b;
    }


    /**
    * 判断全部节点有效
    * @return 返回真或者假
    */
    public boolean isAll() {
    return all;
    }


    /**
    * 增加类型
    * @param who
    */
    public void addType(byte who) {
    if (!types.contains(who)) {
    types.add(who);
    }
    }


    /**
    * 返回类型
    * @return
    */
    public List<java.lang.Byte> getTypes() {
    return new ArrayList<Byte>(types);
    }

    /**
    * 返回类型
    * @return
    */
    public byte[] getTypeBytes() {
    int size = types.size();
    byte[] sites = new byte[size];
    for (int i = 0; i < size; i++) {
    sites[i] = types.get(i);
    }
    return sites;
    }

    /**
    * 判断某个类型的节点存在
    * @param who 节点类型
    * @return 存在返回真,否则假
    */
    public boolean hasType(byte who) {
    return types.contains(who);
    }


    /**
    * 增加用户名称
    * @param siger
    * @return 成功返回真,否则假
    */
    public boolean addUser(Siger siger) {
    if (!users.contains(siger)) {
    return users.add(siger);
    }
    return false;
    }


    /**
    * 判断用户账号存在
    * @param siger
    * @return
    */
    public boolean hasUser(Siger siger) {
    return users.contains(siger);
    }


    /**
    * 返回用户名称
    * @return
    */
    public List<Siger> getUsers() {
    return new ArrayList<Siger>(users);
    }

    /**
    * 保存一个用户明文
    * @param e 字符串
    * @return 保存成功返回真,否则假
    */
    public boolean addText(String e) {
    Laxkit.nullabled(e);

    return texts.add(new Naming(e));
    }


    /**
    * 根据SHA256签名,查找匹配的明文
    * @param hash 用户签名
    * @return 返回用户明文,没有返回SHA256签名
    */
    public String findText(Siger hash) {
    for (Naming e : texts) {
    String name = e.toString();
    // 判断是SHA256码,或者明文
    if (Siger.validate(name)) {
    if (Laxkit.compareTo(name, hash.getHex(), false) == 0) {
    return name;
    }
    } else {
    Siger that = SHAUser.doUsername(name);
    if (that.compareTo(hash) == 0) {
    return name;
    }
    }
    }
    return hash.toString();
    }


    /**
    * 增加命令
    * @param text
    * @return
    */
    public boolean addInclude(String text) {
    Naming naming = new Naming(text);
    return includes.add(naming);
    }


    /**
    * 判断命令存在
    * @param text 文本
    * @return 返回真或者假
    */
    public boolean hasInclude(String text) {
    Naming naming = new Naming(text);
    return includes.contains(naming);
    }

    /**
    * 返回命令数目统计
    * @return 整数
    */
    public int getIncludeCount() {
    return includes.size();
    }

    /**
    * 增加忽略命令
    * @param text
    * @return
    */
    public boolean addExclude(String text) {
    Naming naming = new Naming(text);
    return excludes.add(naming);
    }


    /**
    * 判断忽略命令存在
    * @param text 文本
    * @return 返回真或者假
    */
    public boolean hasExclude(String text) {
    Naming naming = new Naming(text);
    return excludes.contains(naming);
    }

    /**
    * 返回忽略命令数目统计
    * @return 整数
    */
    public int getExcludeCount() {
    return excludes.size();
    }


    /**
    * 设置开始时间
    * @param d
    */
    public void setBeginTime(long d) {
    beginTime = d;
    }

    /**
    * 返回开始时间
    * @return
    */
    public long getBeginTime() {
    return beginTime ;
    }

    /**
    * 设置结束时间
    * @param d
    */
    public void setEndTime(long d) {
    endTime = d;
    }

    /**
    * 返回结束时间
    * @return
    */
    public long getEndTime() {
    return endTime;
    }

    /* (non-Javadoc)
    * @see com.laxcus.command.Command#duplicate()
    */
    @Override
    public CheckUserCost duplicate() {
    return new CheckUserCost(this);
    }


    /* (non-Javadoc)
    * @see com.laxcus.command.Command#buildSuffix(com.laxcus.util.classable.ClassWriter)
    */
    @Override
    protected void buildSuffix(ClassWriter writer) {
    // 节点类型
    int size = types.size();
    writer.writeInt(size);
    for (byte who : types) {
    writer.write(who);
    }
    // 用户
    size = users.size();
    writer.writeInt(size);
    for (Siger siger : users) {
    writer.writeObject(siger);
    }
    // 检查的命令
    size = includes.size();
    writer.writeInt(size);
    for (Naming cmd : includes) {
    writer.writeObject(cmd);
    }
    // 命令
    size = excludes.size();
    writer.writeInt(size);
    for (Naming cmd : excludes) {
    writer.writeObject(cmd);
    }
    // 时间
    writer.writeLong(beginTime);
    writer.writeLong(endTime);
    }


    /* (non-Javadoc)
    * @see com.laxcus.command.Command#resolveSuffix(com.laxcus.util.classable.ClassReader)
    */
    @Override
    protected void resolveSuffix(ClassReader reader) {
    // 节点类型
    int size = reader.readInt();
    for (int i = 0; i < size; i++) {
    byte who = reader.read();
    types.add(who);
    }
    // 用户签名
    size = reader.readInt();
    for (int i = 0; i < size; i++) {
    Siger signer = new Siger(reader);
    users.add(signer);
    }
    // 检索的命令
    size = reader.readInt();
    for (int i = 0; i < size; i++) {
    Naming cmd = new Naming(reader);
    includes.add(cmd);
    }
    // 忽略的命令
    size = reader.readInt();
    for (int i = 0; i < size; i++) {
    Naming cmd = new Naming(reader);
    excludes.add(cmd);
    }
    // 时间
    beginTime = reader.readLong();
    endTime = reader.readLong();
    }


    }
    复制

    Check User Cost类中的变量需要做点解释

    1. 节点类型,它的定义,可以查阅SiteTag类的源代码,目前是除Front节点和Watch节点之外,都能够支持,Front节点和Watch注册用户和系统管理员使用的节点,并不涉及计费问题。如果指定全部节点,那么all变量设成“true”。

    2. 用户签名,对应Siger类,它的本质就是一个SHA256签名。生成SHA256签名可以使用Laxkit类的doSiger方法来实现,doSiger方法的作用是把一个字符串转换成数字签名,输入是字符文本,输出是Siger类。

    3. 查询的命名。在Laxcus集群里,所有分布式计算工作都有一个名称,比如执行大型的分布式计算工作,对应CONDUCT名称,如果上传文件到云端,对应UPLOAD CLOUD FILE名称。依此类推。Naming的作用是忽略大小写,即一个 CONDUCT和conduct等价。如果置空,表示搜索与用户签名相关的全部命令

    4. 忽略的命令。它的作用和查询命名相反,即不查询某些命名。

    5. 开始、结束命令。这个参数是一个长整数值,使用转义函数来取得。


    比如我们想查询2022年12月1日到2022年12月2日两天,一个名为“Tubex“的用户记录,但是不包括CONDUCT命名,那么生成CheckUserCost的命令可以这样写:

      CheckUserCost cmd = new CheckUserCost();
      cmd.setAll(true);
      Siger siger = Laxkit.doSiger(“tubex”);
      cmd.addUser(siger);
      cmd.addExclude(new Naming("conduct"));
      long timestamp = CalendarGenerator.splitTimestamp("2022-12-1");
      cmd.setBeginTime(timestamp);
      timestamp = CalendarGenerator.splitTimestamp("2022-12-2");
      cmd.setEndTime(timestamp);
      复制

      二、Check User Cost命令的返回结果

      Check User Cost命令的返回结果对应CheckUserCostProduct类,CheckUserCostProduct继承自EchoProduct,保存所有检索结果。参数是基于用户签名和查询单元的TreeMap,CheckUserCostProduct类中包含了UserCostElement类,而UserCostElement类又包含UserCostItem类,这样就形成了“CheckUserCostProduct -> CheckUserCostElement -> UserCostItem”三级关系。因为CheckUserCostProduct类和UserCostElement类比较简单,咱们重点说说UserCostItem类。如果开发者想增加更多的计费元素,可以结合需求调用系统底层修改UserCostItem的源代码。

      UserCostItem源代码如下:

        public final class UserCostItem implements Classable, Cloneable, Serializable, Comparable<UserCostItem> {


        private static final long serialVersionUID = -6293384810197643693L;


        /** 节点类型 **/
        private byte family;

        /** 调用器编号 **/
        private long invokerId;

        /** 迭代次数 **/
        private int iterateIndex;

        /** 操作命名 **/
        private String command;


        /** 开始和结束时间 **/
        private long initTime, endTime;

        /** 被线程调用,在EchoInvoker中的迭代时间 **/
        private long threadIterateTime;

        /** 接收数据流量 **/
        private long receiveFlows;

        /** 发送数据流量 **/
        private long sendFlows;

        /** 服务号,对应Command的slogan,全局唯一 **/
        private long slogan;

        /** 服务迭代编号,对应服务号,根据分布流程,从1开始逐次传递增加 **/
        private int sloganIndex;

        /** 命令级别,对应Command类 **/
        private byte priority;

        /**
        * 构造默认的被刷新处理单元
        */
        public UserCostItem() {
        super();
        family = 0;
        invokerId = 0;
        iterateIndex = 0;
        command = null;
        initTime = 0;
        endTime = 0;
        threadIterateTime = 0;
        receiveFlows = 0;
        sendFlows = 0;
        slogan = 0;
        sloganIndex = 0;
        priority = 0;
        }


        /**
        * 根据传入实例,生成用户消费单元的数据副本
        * @param that UserCostItem实例
        */
        private UserCostItem(UserCostItem that) {
        super();
        family = that.family;
        invokerId = that.invokerId;
        iterateIndex = that.iterateIndex;
        command = that.command;
        initTime = that.initTime;
        endTime = that.endTime;
        threadIterateTime = that.threadIterateTime;
        receiveFlows = that.receiveFlows;
        sendFlows = that.sendFlows;
        slogan = that.slogan;
        sloganIndex = that.sloganIndex;
        priority = that.priority;
        }


        /**
        * 从可类化数据读取器中用户消费单元
        * @param reader 可类化数据读取器
        */
        public UserCostItem(ClassReader reader) {
        this();
        resolve(reader);
        }


        /**
        * 设置节点类型
        * @param who
        */
        public void setFamily(byte who) {
        family = who;
        }


        /**
        * 返回节点类型
        * @return
        */
        public byte getFamily() {
        return family;
        }


        /**
        * 设置调用器编号
        * @param id 编号
        */
        public void setInvokerId(long id) {
        invokerId = id;
        }


        /**
        * 返回调用器编号
        * @return 毫秒
        */
        public long getInvokerId() {
        return invokerId;
        }

        /**
        * 设置迭代次数
        * @param i
        */
        public void setIterateIndex(int i) {
        iterateIndex = i;
        }


        /**
        * 返回迭代次数
        * @return
        */
        public int getIterateIndex() {
        return iterateIndex;
        }


        /**
        * 设置命令
        * @param s
        */
        public void setCommand(String s) {
        command = s;
        }


        /**
        * 返回命令
        * @return
        */
        public String getCommand() {
        return command;
        }


        /**
        * 设置初始时间
        * @param ms
        */
        public void setInitTime(long ms) {
        initTime = ms;
        }


        /**
        * 返回初始时间
        * @return
        */
        public long getInitTime() {
        return initTime;
        }


        /**
        * 设置结束时间
        * @param ms
        */
        public void setEndTime(long ms) {
        endTime = ms;
        }


        /**
        * 返回结束时间
        * @return
        */
        public long getEndTime() {
        return endTime;
        }


        /**
        * 设置被线程调用,在EchoInvoker中的迭代时间
        * @param ms 毫秒
        */
        public void setThreadIterateTime(long ms) {
        threadIterateTime = ms;
        }


        /**
        * 返回被线程调用,在EchoInvoker中的迭代时间
        * @return 毫秒
        */
        public long getThreadIterateTime() {
        return threadIterateTime;
        }

        /**
        * 设置接收数据流尺寸
        * @param len 数据长度
        */
        public void setReceiveFlows(long len) {
        receiveFlows = len;
        }


        /**
        * 返回接收数据流尺寸
        * @return 数据长度
        */
        public long getReceiveFlows() {
        return receiveFlows;
        }

        /**
        * 设置发送数据流尺寸
        * @param len 数据长度
        */
        public void setSendFlows(long len) {
        sendFlows = len;
        }


        /**
        * 返回发送数据流尺寸
        * @return 数据长度
        */
        public long getSendFlows() {
        return sendFlows;
        }

        /**
        * 设置服务号
        * @param no 服务号
        */
        public void setSlogan(long no) {
        slogan = no;
        }


        /**
        * 返回服务号
        * @return 服务号
        */
        public long getSlogan() {
        return slogan;
        }


        /**
        * 设置服务编号,不定义是0
        * @param no 长整型
        */
        public void setSloganIndex(int no) {
        sloganIndex = no;
        }


        /**
        * 返回服务编号
        * @return 长整型
        */
        public int getSloganIndex() {
        return sloganIndex;
        }

        /**
        * 设置命令优先级
        * @param no 命令优先级
        */
        public void setPriority(byte no) {
        priority = no;
        }


        /**
        * 返回命令优先级
        * @return 命令优先级
        */
        public byte getPriority() {
        return priority;
        }


        /**
        * 生成当前实例的数据副本
        * @return UserCostItem实例
        */
        public UserCostItem duplicate() {
        return new UserCostItem(this);
        }


        /*
        * (non-Javadoc)
        * @see java.lang.Object#clone()
        */
        @Override
        public Object clone() {
        return duplicate();
        }


        /*
        * (non-Javadoc)
        * @see java.lang.Object#hashCode()
        */
        @Override
        public int hashCode() {
        return (int) ((invokerId >>> 32) ^ invokerId);
        }


        /*
        * (non-Javadoc)
        * @see java.lang.Object#equals(java.lang.Object)
        */
        @Override
        public boolean equals(Object that) {
        if (that == null || getClass() != that.getClass()) {
        return false;
        } else if (that == this) {
        return true;
        }
        // 比较
        return compareTo((UserCostItem ) that) == 0;
        }


        /* (non-Javadoc)
        * @see java.lang.Comparable#compareTo(java.lang.Object)
        */
        @Override
        public int compareTo(UserCostItem that) {
        int ret = Laxkit.compareTo(family, that.family);
        if (ret == 0) {
        ret = Laxkit.compareTo(initTime, that.initTime);
        }
        if (ret == 0) {
        ret = Laxkit.compareTo(command, that.command, false);
        }
        if (ret == 0) {
        ret = Laxkit.compareTo(invokerId, that.invokerId);
        }
        return ret;
        }

        /* (non-Javadoc)
        * @see com.laxcus.util.Classable#build(com.laxcus.util.ClassWriter)
        */
        @Override
        public int build(ClassWriter writer) {
        int size = writer.size();
        buildSuffix(writer);
        return writer.size() - size;
        }


        /* (non-Javadoc)
        * @see com.laxcus.util.Classable#resolve(com.laxcus.util.ClassReader)
        */
        @Override
        public int resolve(ClassReader reader) {
        int seek = reader.getSeek();
        resolveSuffix(reader);
        return reader.getSeek() - seek;
        }


        /**
        * 保存参数
        * @param writer
        */
        protected void buildSuffix(ClassWriter writer) {
        writer.write(family);
        writer.writeLong(invokerId);
        writer.writeInt(iterateIndex);
        writer.writeString(command);

        writer.writeLong(initTime);
        writer.writeLong(endTime);
        writer.writeLong(threadIterateTime);

        writer.writeLong(receiveFlows);
        writer.writeLong(sendFlows);

        writer.writeLong(slogan);
        writer.writeInt(sloganIndex);
        writer.write(priority);
        }


        /**
        * 解析参数
        * @param reader
        */
        protected void resolveSuffix(ClassReader reader) {
        family = reader.read();
        invokerId = reader.readLong();
        iterateIndex = reader.readInt();
        command = reader.readString();


        initTime = reader.readLong();
        endTime = reader.readLong();
        threadIterateTime = reader.readLong();


        receiveFlows = reader.readLong();
        sendFlows = reader.readLong();

        slogan = reader.readLong();
        sloganIndex = reader.readInt();
        priority = reader.read();
        }


        }
        复制

        下面说说UserCostItem比较重要的一些参数,通过这些参数,结合计费算法规则,你将最终得到你的计费

        1. family,节点类型,它对应SiteTag中的节点类型

        2. invokerId,调用器编号,也可以理解为进程编号。如果查阅系统日志,把它和节点类型结合,可以定位提取出调用器产生的运行记录。

        3. iterateIndex,迭代次数。Laxcus调用器存在被系统多次调用的可能,迭代编号是指它循环执行的次数。多次迭代之间,调用器会被系统悬挂起来,直到运行条件满足再次触发执行。迭代次数理论上最少1次,最多不限。

        4. command,操作命名,这个参数对应CheckUserCost中的includes参数。

        5. initTime, endTime,调用器的第一次启动时间和最后时间,两个参数的差值,就是调用器运行的总时间。如果以时间为标准进行计费,通过这个时间,结合计费结合,可以得出一个计费结果。

        6. receiveFlows,调用器在分布计算过程中,接收得到的数据流量。流量以字节为单位,这个参数通常是各种计费标准的主要依据之一。

        7. sendFlows,调用器在分布计算过程中,发送出去的数据流量。这个参数同样也是计费标准参照之一。

        8. slogan,服务号,是一个64位的整数值。它在分布计算执行前由系统赋值,保证运行环境全局唯一,如果分布计算过程中产生了分裂(类似Linux编程中的fork),这个服务号也会被继承下来。通过服务号,无论分布计算在多少个节点执行,其间发生了多少次分裂,都可以把它们记录下来,然后反向推导出分布计算执行的先后顺序和分布执行情况。如果有需要,在这个基础上,进一步形成可视化的分布计算执行流程图表,必要时提供给用户,作为分布计算的佐证之一。

        9. sloganIndex,服务迭代编号,即关联服务号的调用器,在分布式计算过程中发生了分裂,就在这个编号上做一个加1的操作。服务迭代编号从1开始,随着调用器分裂逐层传递增加。

        10. priority,操作执行优先级,前一篇说过,用户的分布业务,有四个级别,从大到小分为MAX级,NORMAL级,MINI级,NONE级。调整用户优先级由管理员来操作,默认情况下,所有用户都是NONE级,即不定义优先级。获得更高优先级应用业务,总是比低于它一级的应用业务,优先取得Laxcus计算机集群的资源,优先取得执行权限进行分布计算工作。所以priority也是一个计费参照之一,更高优先级的业务,在享受优先处理权利时,也应该付出更多的消费金额。


        下面是UserCostElement类和CheckUserCostProduct类的源程序代码,因为比较简单,就不单独说明了。

          public final class UserCostElement implements Classable, Cloneable, Serializable, Comparable<UserCostElement> {


          private static final long serialVersionUID = 5651643178030182283L;


          /** 用户签名 **/
          private Siger issuer;


          /** 未使用容量 **/
          private TreeSet<UserCostItem> array = new TreeSet<UserCostItem>();

          /**
          * 构造默认的用户资源消耗成员
          */
          public UserCostElement() {
          super();
          }


          /**
          * 构造用户资源消耗成员
          * @param issuer 用户签名
          */
          public UserCostElement(Siger issuer) {
          this();
          setIssuer(issuer);
          }

          /**
          * 根据传入实例,生成用户资源消耗成员的数据副本
          * @param that UserCostElement实例
          */
          private UserCostElement(UserCostElement that) {
          super();
          issuer = that.issuer;
          array.addAll(that.array);
          }


          /**
          * 从可类化数据读取器中用户资源消耗成员
          * @param reader 可类化数据读取器
          */
          public UserCostElement(ClassReader reader) {
          this();
          resolve(reader);
          }


          /**
          * 设置用户签名
          * @param who 签名
          */
          public void setIssuer(Siger who) {
          issuer = who;
          }


          /**
          * 返回用户签名
          * @return 签名
          */
          public Siger getIssuer() {
          return issuer;
          }


          /**
          * 加一个单元
          * @param item
          * @return
          */
          public boolean add(UserCostItem item) {
          if (item != null) {
          return array.add(item);
          }
          return false;
          }

          /**
          * 增加一批单元
          * @param a
          * @return
          */
          public int addAll(Collection<UserCostItem> a) {
          int size = array.size();
          if (a != null) {
          for (UserCostItem item : a) {
          add(item);
          }
          }
          return array.size() - size;
          }


          /**
          * 返回单元
          * @return
          */
          public List<UserCostItem> list() {
          return new ArrayList<UserCostItem>(array);
          }


          /**
          * 全部成员
          * @return
          */
          public int size() {
          return array.size();
          }

          /**
          * 生成当前实例的数据副本
          * @return UserCostElement实例
          */
          public UserCostElement duplicate() {
          return new UserCostElement(this);
          }


          /*
          * (non-Javadoc)
          * @see java.lang.Object#clone()
          */
          @Override
          public Object clone() {
          return duplicate();
          }


          /*
          * (non-Javadoc)
          * @see java.lang.Object#equals(java.lang.Object)
          */
          @Override
          public boolean equals(Object that) {
          if (that == null || getClass() != that.getClass()) {
          return false;
          } else if (that == this) {
          return true;
          }
          // 比较
          return compareTo((UserCostElement) that) == 0;
          }


          /* (non-Javadoc)
          * @see java.lang.Comparable#compareTo(java.lang.Object)
          */
          @Override
          public int compareTo(UserCostElement that) {
          if (that == null) {
          return 1;
          }
          // 比较参数
          return Laxkit.compareTo(issuer, that.issuer);
          }


          /* (non-Javadoc)
          * @see com.laxcus.util.Classable#build(com.laxcus.util.ClassWriter)
          */
          @Override
          public int build(ClassWriter writer) {
          int size = writer.size();
          buildSuffix(writer);
          return writer.size() - size;
          }


          /* (non-Javadoc)
          * @see com.laxcus.util.Classable#resolve(com.laxcus.util.ClassReader)
          */
          @Override
          public int resolve(ClassReader reader) {
          int seek = reader.getSeek();
          resolveSuffix(reader);
          return reader.getSeek() - seek;
          }


          /**
          * 保存参数
          * @param writer
          */
          protected void buildSuffix(ClassWriter writer) {
          writer.writeObject(issuer);
          int size = array.size();
          writer.writeInt(size);
          for (UserCostItem e : array) {
          writer.writeObject(e);
          }
          }


          /**
          * 解析参数
          * @param reader
          */
          protected void resolveSuffix(ClassReader reader) {
          issuer = new Siger(reader);
          int size = reader.readInt();
          for (int i = 0; i < size; i++) {
          UserCostItem item = new UserCostItem(reader);
          add(item);
          }
          }


          }
          复制
            public class CheckUserCostProduct extends EchoProduct {


            private static final long serialVersionUID = 3146106632408001248L;


            /** 用户签名 -> 单元 **/
            private Map<Siger, UserCostElement> array = new TreeMap<Siger, UserCostElement>();


            /**
            * 构造默认的服务器系统信息检测结果
            */
            public CheckUserCostProduct() {
            super();
            }


            /**
            * 从可类化数据读取器解析服务器系统信息检测结果
            * @param reader 可类化数据读取器
            */
            public CheckUserCostProduct(ClassReader reader) {
            this();
            resolve(reader);
            }


            /**
            * 构造服务器系统信息检测结果的数据副本
            * @param that CheckUserCostProduct实例
            */
            private CheckUserCostProduct(CheckUserCostProduct that) {
            super(that);
            array.putAll(that.array);
            }


            /**
            * 加一个
            * @param product
            */
            public void add(CheckUserCostProduct product) {
            for (UserCostElement element : product.array.values()) {
            add(element.getIssuer(), element);
            }
            }


            /**
            * 加全部
            * @param issuer 用户签名
            * @param element 成员
            */
            public void add(Siger issuer, UserCostElement element) {
            UserCostElement that = array.get(issuer);
            if (that != null) {
            that.addAll(element.list());
            } else {
            array.put(issuer, element);
            }
            }


            /**
            * 加一个单元
            * @param issuer 签名
            * @param item 成员
            */
            public void add(Siger issuer, UserCostItem item) {
            UserCostElement element = array.get(issuer);
            if (element != null) {
            element.add(item);
            } else {
            element = new UserCostElement(issuer);
            element.add(item);
            array.put(element.getIssuer(), element);
            }
            }


            /**
            * 输出全部
            * @return
            */
            public List<UserCostElement> list() {
            return new ArrayList<UserCostElement>(array.values());
            }

            /**
            * 查找一个成员
            * @param siger 签名
            * @return 返回匹配的成员
            */
            public UserCostElement find(Siger siger) {
            return array.get(siger);
            }


            /**
            * 判断是空
            * @return
            */
            public boolean isEmpty() {
            return array.isEmpty();
            }


            /**
            * 有效单元数目
            * @return 整数
            */
            public int size() {
            return array.size();
            }


            /* (non-Javadoc)
            * @see com.laxcus.echo.product.EchoProduct#duplicate()
            */
            @Override
            public CheckUserCostProduct duplicate() {
            return new CheckUserCostProduct(this);
            }


            /* (non-Javadoc)
            * @see com.laxcus.echo.product.EchoProduct#buildSuffix(com.laxcus.util.ClassWriter)
            */
            @Override
            protected void buildSuffix(ClassWriter writer) {
            writer.writeInt(array.size());
            for (UserCostElement e : array.values()) {
            writer.writeObject(e);
            }
            }


            /* (non-Javadoc)
            * @see com.laxcus.echo.product.EchoProduct#resolveSuffix(com.laxcus.util.ClassReader)
            */
            @Override
            protected void resolveSuffix(ClassReader reader) {
            int size = reader.readInt();
            for (int i = 0; i < size; i++) {
            UserCostElement element = new UserCostElement(reader);
            add(element.getIssuer(), element);
            }
            }


            }
            复制

            最后,我们需要把它们整合起来,编写成计算机程序,投递给Laxcus计算机集群来处理,这里的代码就非常简单,只有以下几步:

            1.生成命令 (这步上面已经演示)

            2.生成一个异步监听接口,和命令一起,交给命令分派接口处理。

            3.调用Laxcus分布式操作系统DSDK中的命令分派接口,把命令和异步监听器投递给它,DSDK让命令分派接口投递给Laxcus集群处理。

            4.异步监听接口收到反馈结果,解析CheckUsetCostProduct中的参数,结合计费算法,得出计费结果。

            这些步骤集合起来,就是下面这样一段代码:

                class CheckUserCostProductListener implements ProductListener {


              @Override
              public void push(Object e) {
              boolean success = (e != null && e.getClass() == CheckUserCostProduct.class);
              if (!success) {
              // 不成功,做出错的处理
              return;
              }
              // 成功,提取返回参数,结束计费算法,得出计费结果
              }
              }

              // 1. 生成命令
              CheckUserCost cmd = new CheckUserCost();
              cmd.setAll(true);
              Siger siger = Laxkit.doSiger("tubex");
              cmd.addUser(siger);
              cmd.addExclude(new Naming("conduct"));
              long timestamp = CalendarGenerator.splitTimestamp("2022-12-1");
              cmd.setBeginTime(timestamp);
              timestamp = CalendarGenerator.splitTimestamp("2022-12-2");
              cmd.setEndTime(timestamp);
              // 2. 生成异步监听器,返回结果将投递给它处理
              CheckUserCostProductListener listner = new CheckUserCostProductListener();
              // 3. 生成交互适配器,在命令投递进入集群前出现错误,将由它来处理和显示
              MeetDisplayAdapter adapter = new MeetDisplayAdapter(listener);
              // 4. 调用系统API,把命令投递给集群处理
              CommandDispatcher dispatcher = PlatformKit.findListener(CommandDispatcher.class);
              dispatcher.submit(cmd, true, new CommandAuditorAdapter(), adapter);
              复制

              上面的代码通过编译,结合系统的图形界面,做成Laxcus分布式操作系统的应用软件,就可以在管理员桌面上运行了。

              另外,如果是在Laxcus管理员桌面环境以外运行,那么就要把DSDK集成起来,并且连接进入Laxcus集群,才能执行上面的操作。

              至此,一个简单的Laxcus云服务计费系统设计完成。有兴趣不妨去试试,把它“润”起来,看看你的Laxcus云服务有多少人在使用,他们在执行什么工作,消耗了多少计算机资源,也或者看看有什么改进工作要做吧。



              Laxcus是一个提供云服务,开源、容错、高扩展、多人共享、多机协同分布运行的操作系统,实现了数存算一体化,云边端协同,通过分布式应用软件,聚合数据、算力、机器算法,处理大规模、超大规模的存储和计算工作。企业版支持百万级节点规模的计算机集群、亿级用户在线。

              了解更多Laxcus分布式操作系统安装使用部署,图形设计、网络通信、分布式存储、大数据、分布式计算、边缘计算、人工智能、云原生、安全管理、开发分布式应用软件和其它前沿技术,请关注公众号“Laxcus分布式操作系统”,或者联系小编微信,加入产品技术群,让我们一起讨论最新的产品技术知识。


              文章转载自LAXCUS分布式操作系统,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论