dubbo泛化处理

关于泛化,dubbo文档这样描述的。

http://dubbo.io/User+Guide-zh.htm#UserGuide-zh-%E6%B3%9B%E5%8C%96%E5%BC%95%E7%94%A8

泛接口调用方式主要用于客户端没有API接口及模型类元的情况,参数及返回值中的所有POJO均用Map表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过GenericService调用所有服务实现。

http://dubbo.io/User+Guide-zh.htm#UserGuide-zh-%E6%B3%9B%E5%8C%96%E5%AE%9E%E7%8E%B0

泛接口实现方式主要用于服务器端没有API接口及模型类元的情况,参数及返回值中的所有POJO均用Map表示,通常用于框架集成,比如:实现一个通用的远程服务Mock框架,可通过实现GenericService接口处理所有服务请求。


总的意思来说,某些环境(通用网关、服务端Mock),dubbo接口和类的参数、返回值的类型可能不能加载。为了这些环境也能调用/实现dubbo服务,dubbo框架会对参数和返回值进行泛化(序列)处理,默认处理为Map表示的字符串。虽然文档没有介绍,实际上,dubbo还支持另外两种泛化处理--nativejava(利用java原生序列化)、bean(序列化为JavaBeanDescriptor)。


dubbo通过filter实现泛化:

调用 <-> GenericImplFilter <->网络<->GenericFilter <-> 服务实现

GenericImplFilter和GenericFilter分别在消费者端和提供者端进行序列化的检查和处理。


我们的网关也是直接调用dubbo的,因为dubbo的接口类不能在网关侧加载,所以,需要泛化调用。但是,我们网关调用的dubbo服务的参数和返回值都是通用类型,在网关侧也能加载的。并且,网关侧还需要对返回值进行进一步处理。所以,如果像默认dubbo泛化那样序列化为包含String的Map,那我处理前还需要再反序列化,这比较麻烦(需要确保被反序列化的POJO),性能也不高。


要解决这种问题,可以新增一种泛化类型。

public static final String GENERIC_SERIALIZATION_NOCHANGE      = "nochange";

    public static boolean isGeneric(String generic) {
        return generic != null
            && !"".equals(generic)
            && (Constants.GENERIC_SERIALIZATION_DEFAULT.equalsIgnoreCase(generic)  /* 正常的泛化调用 */
            || Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic) /* 支持java序列化的流式泛化调用 */
            || Constants.GENERIC_SERIALIZATION_BEAN.equalsIgnoreCase(generic)
            || Constants.GENERIC_SERIALIZATION_NOCHANGE.equalsIgnoreCase(generic));
    }


并且,GenericFilter中发现如果是这种泛化类型,那么不对服务实现的返回值进行序列化处理。

                } else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
                    return new RpcResult(JavaBeanSerializeUtil.serialize(result.getValue(), JavaBeanAccessor.METHOD));
                } else if (ProtocolUtils.isNoChangeGenericSerialization(generic)) {
                    return new RpcResult(result.getValue());

                } else {
                    return new RpcResult(PojoUtils.generalize(result.getValue()));
                }


这样,只要初始化时设置好泛化类型,genericService.$invoke获得的返回值就直接是服务端的值,不是Map等表示的值。

        ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
        reference.setApplication(application);
        reference.setRegistries(registries);
        reference.setInterface(serverInterface);
        reference.setGeneric(Constants.GENERIC_SERIALIZATION_NOCHANGE);

你可能感兴趣的:(dubbo泛化处理)