storm代码阅读(三)

2021SC@SDUSC

storm代码阅读(三)

2021SC@SDUSC

TopologyBuilder中一些接口的实现

ConfigGetter

ConfigGetter是定义在TopologyBuilder.java中的一个类,它实现了ComponentConfigurationDeclarer接口,并且继承自BaseConfigurationDeclarer类。

ConfigGetter作用:设置程序中的配置项,覆盖默认的配置项,且配置项的格式为为JSON(本质上是改变对应ComponentCommon对象中json_conf的值)。

具体代码如下:

    protected class ConfigGetter<T extends ComponentConfigurationDeclarer> extends BaseConfigurationDeclarer<T> {
        String id;

        public ConfigGetter(String id) {
            this.id = id;
        }

        @SuppressWarnings("unchecked")
        @Override
        public T addConfigurations(Map<String, Object> conf) {
            if (conf != null) {
                if (conf.containsKey(Config.TOPOLOGY_KRYO_REGISTER)) {
                    throw new IllegalArgumentException("Cannot set serializations for a component using fluent API");
                }
                if (!conf.isEmpty()) {
                    String currConf = commons.get(id).get_json_conf();
                    commons.get(id).set_json_conf(mergeIntoJson(parseJson(currConf), conf));
                }
            }
            return (T) this;
        }

        /**
         * return the current component configuration.
         *
         * @return the current configuration.
         */
        @Override
        public Map<String, Object> getComponentConfiguration() {
            return parseJson(commons.get(id).get_json_conf());
        }

        @Override
        public T addResources(Map<String, Double> resources) {
            if (resources != null && !resources.isEmpty()) {
                String currConf = commons.get(id).get_json_conf();
                Map<String, Object> conf = parseJson(currConf);
                Map<String, Double> currentResources =
                    (Map<String, Double>) conf.computeIfAbsent(Config.TOPOLOGY_COMPONENT_RESOURCES_MAP, (k) -> new HashMap<>());
                currentResources.putAll(resources);
                commons.get(id).set_json_conf(JSONValue.toJSONString(conf));
            }
            return (T) this;
        }

        @SuppressWarnings("unchecked")
        @Override
        public T addResource(String resourceName, Number resourceValue) {
            Map<String, Object> componentConf = parseJson(commons.get(id).get_json_conf());
            Map<String, Double> resourcesMap = (Map<String, Double>) componentConf.computeIfAbsent(
                Config.TOPOLOGY_COMPONENT_RESOURCES_MAP, (k) -> new HashMap<>());

            resourcesMap.put(resourceName, resourceValue.doubleValue());

            return addConfiguration(Config.TOPOLOGY_COMPONENT_RESOURCES_MAP, resourcesMap);
        }

        @SuppressWarnings("unchecked")
        @Override
        public T addSharedMemory(SharedMemory request) {
            SharedMemory found = sharedMemory.get(request.get_name());
            if (found != null && !found.equals(request)) {
                throw new IllegalArgumentException("Cannot have multiple different shared memory regions with the same name");
            }
            sharedMemory.put(request.get_name(), request);
            Set<String> mems = componentToSharedMemory.computeIfAbsent(id, (k) -> new HashSet<>());
            mems.add(request.get_name());
            return (T) this;
        }
    }

其中id代表组件的唯一标识符。在通常的非事务流处理中不能设定组件的序列化方法,只能使用系统默认的序列化方法。ConfigGetter会根据新设置的配置项覆盖组件默认的配置项,最终,配置项会被序列化为JSON格式。

SpoutGetter

SpoutGetter实现了基本上和CinfigGetter相同的功能,唯一的不同是Spout不需要对输入进行声明。

具体代码如下:

    protected class SpoutGetter extends ConfigGetter<SpoutDeclarer> implements SpoutDeclarer {
        public SpoutGetter(String id) {
            super(id);
        }
    }

BoltGetter

BoltGetter继承自ConfigGetter实现了对于Bolt组建的配置定制,还实现了BoltDeclarer接口,并重载了BoltDeclarer(InputDeclarer)中各种分组方式(如:fieldsGrouping、shuffleGrouping),分组方式的实现本质上是在_commons中通过对用的boltId找到对应的ComponentCommon对象,对inputs属性进行设置。

具体代码如下:

    protected class BoltGetter extends ConfigGetter<BoltDeclarer> implements BoltDeclarer {
        private String boltId;

        public BoltGetter(String boltId) {
            super(boltId);
            this.boltId = boltId;
        }

        public BoltDeclarer fieldsGrouping(String componentId, Fields fields) {
            return fieldsGrouping(componentId, Utils.DEFAULT_STREAM_ID, fields);
        }

        public BoltDeclarer fieldsGrouping(String componentId, String streamId, Fields fields) {
            return grouping(componentId, streamId, Grouping.fields(fields.toList()));
        }

        public BoltDeclarer globalGrouping(String componentId) {
            return globalGrouping(componentId, Utils.DEFAULT_STREAM_ID);
        }

        public BoltDeclarer globalGrouping(String componentId, String streamId) {
            return grouping(componentId, streamId, Grouping.fields(new ArrayList<String>()));
        }

        public BoltDeclarer shuffleGrouping(String componentId) {
            return shuffleGrouping(componentId, Utils.DEFAULT_STREAM_ID);
        }

        public BoltDeclarer shuffleGrouping(String componentId, String streamId) {
            return grouping(componentId, streamId, Grouping.shuffle(new NullStruct()));
        }

        public BoltDeclarer localOrShuffleGrouping(String componentId) {
            return localOrShuffleGrouping(componentId, Utils.DEFAULT_STREAM_ID);
        }

        public BoltDeclarer localOrShuffleGrouping(String componentId, String streamId) {
            return grouping(componentId, streamId, Grouping.local_or_shuffle(new NullStruct()));
        }

        public BoltDeclarer noneGrouping(String componentId) {
            return noneGrouping(componentId, Utils.DEFAULT_STREAM_ID);
        }

        public BoltDeclarer noneGrouping(String componentId, String streamId) {
            return grouping(componentId, streamId, Grouping.none(new NullStruct()));
        }

        public BoltDeclarer allGrouping(String componentId) {
            return allGrouping(componentId, Utils.DEFAULT_STREAM_ID);
        }

        public BoltDeclarer allGrouping(String componentId, String streamId) {
            return grouping(componentId, streamId, Grouping.all(new NullStruct()));
        }

        public BoltDeclarer directGrouping(String componentId) {
            return directGrouping(componentId, Utils.DEFAULT_STREAM_ID);
        }

        public BoltDeclarer directGrouping(String componentId, String streamId) {
            return grouping(componentId, streamId, Grouping.direct(new NullStruct()));
        }

        private BoltDeclarer grouping(String componentId, String streamId, Grouping grouping) {
            commons.get(boltId).put_to_inputs(new GlobalStreamId(componentId, streamId), grouping);
            return this;
        }

        @Override
        public BoltDeclarer grouping(GlobalStreamId id, Grouping grouping) {
            return grouping(id.get_componentId(), id.get_streamId(), grouping);
        }

        @Override
        public BoltDeclarer partialKeyGrouping(String componentId, Fields fields) {
            return customGrouping(componentId, new PartialKeyGrouping(fields));
        }

        @Override
        public BoltDeclarer partialKeyGrouping(String componentId, String streamId, Fields fields) {
            return customGrouping(componentId, streamId, new PartialKeyGrouping(fields));
        }

        @Override
        public BoltDeclarer customGrouping(String componentId, CustomStreamGrouping grouping) {
            return customGrouping(componentId, Utils.DEFAULT_STREAM_ID, grouping);
        }

由于分组方法较多且类似,这里以fieldsGrouping为例进行分析。

第二行定义的boltId变量用于保存Bolt组件的唯一标识符。
接下来的BoltGetter为构造函数,调用了ConfigGetter的构造函数实现配置项的定制功能。
接下来定义了fieldsGrouping及其重载方法,参数包括componentId、 streamId和 fields(用来分组的字段名列表),如果没有指定的streamId将默认使用default作为streamId。

下面的BoltDeclarer grouping是InputDeclarer接口最主要的实现方法。输入含义为:按照grouping参数定义的分组方式,将参数componentId指定的组件中以streamId定义的流放在本组件的输入定义中。其中方法最后一行的return this返回this指针可以通过函数级联的方式为本组件添加更多的输入。
紧接着是该方法的一个重要重载,输入为GlobalStreamId和分组方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值