codec factory 的创建
codec factory 对象的创建被定义在方法 NewCodecFactory() 中,该方法内部调用了 newSerializersForScheme() 方法来创建支持不同数据格式的 Serializer 对象,然后又调用 newCodecFactory() 方法来实现对象创建。
newSerializersForScheme() 方法主要是创建支持各种数据格式 (json, yaml, protobuf 等) 的 serializer 对象,例如之前我们介绍支持 jason 格式的 serializer.json.Serializer,其核心逻辑如下:


newSerializersForScheme() 的源码如下:
// k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.gofunc newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, options CodecFactoryOptions) []serializerType {jsonSerializer := json.NewSerializerWithOptions(mf, scheme, scheme,json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict},)jsonSerializerType := serializerType{AcceptContentTypes: []string{runtime.ContentTypeJSON},ContentType: runtime.ContentTypeJSON,FileExtensions: []string{"json"},EncodesAsText: true,Serializer: jsonSerializer,Framer: json.Framer,StreamSerializer: jsonSerializer,}if options.Pretty {jsonSerializerType.PrettySerializer = json.NewSerializerWithOptions(mf, scheme, scheme,json.SerializerOptions{Yaml: false, Pretty: true, Strict: options.Strict},)}yamlSerializer := json.NewSerializerWithOptions(mf, scheme, scheme,json.SerializerOptions{Yaml: true, Pretty: false, Strict: options.Strict},)protoSerializer := protobuf.NewSerializer(scheme, scheme)protoRawSerializer := protobuf.NewRawSerializer(scheme, scheme)serializers := []serializerType{jsonSerializerType,{AcceptContentTypes: []string{runtime.ContentTypeYAML},ContentType: runtime.ContentTypeYAML,FileExtensions: []string{"yaml"},EncodesAsText: true,Serializer: yamlSerializer,},{AcceptContentTypes: []string{runtime.ContentTypeProtobuf},ContentType: runtime.ContentTypeProtobuf,FileExtensions: []string{"pb"},Serializer: protoSerializer,Framer: protobuf.LengthDelimitedFramer,StreamSerializer: protoRawSerializer,},}for _, fn := range serializerExtensions {if serializer, ok := fn(scheme); ok {serializers = append(serializers, serializer)}}return serializers}
在 newCodecFactory() 这个方法里面,主要逻辑就是调用 newSerializersForScheme()方法,用来生成可以支持各种不同数据类型的 serializerType 数组, 然后利用该数组进行封装创建 codc factory,逻辑如下:

// k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.gofunc newCodecFactory(scheme *runtime.Scheme, serializers []serializerType) CodecFactory {decoders := make([]runtime.Decoder, 0, len(serializers))var accepts []runtime.SerializerInfoalreadyAccepted := make(map[string]struct{})var legacySerializer runtime.Serializerfor _, d := range serializers {decoders = append(decoders, d.Serializer)for _, mediaType := range d.AcceptContentTypes {if _, ok := alreadyAccepted[mediaType]; ok {continue}alreadyAccepted[mediaType] = struct{}{}info := runtime.SerializerInfo{MediaType: d.ContentType,EncodesAsText: d.EncodesAsText,Serializer: d.Serializer,PrettySerializer: d.PrettySerializer,}mediaType, _, err := mime.ParseMediaType(info.MediaType)if err != nil {panic(err)}parts := strings.SplitN(mediaType, "/", 2)info.MediaTypeType = parts[0]info.MediaTypeSubType = parts[1]if d.StreamSerializer != nil {info.StreamSerializer = &runtime.StreamSerializerInfo{Serializer: d.StreamSerializer,EncodesAsText: d.EncodesAsText,Framer: d.Framer,}}accepts = append(accepts, info)if mediaType == runtime.ContentTypeJSON {legacySerializer = d.Serializer}}}if legacySerializer == nil {legacySerializer = serializers[0].Serializer}return CodecFactory{scheme: scheme,universal: recognizer.NewDecoder(decoders...),accepts: accepts,legacySerializer: legacySerializer,}}
codec 的创建
codec factory 对象的 DecoderToVersion() 方法和 EncoderForVersion() 方法会创建 codec 对象。而这两个方法又都会去调用相同的 NewDefaultingCodecForScheme() 方法,最终这个方法又调用 NewCodec() 实现创建。
DecoderToVersion()和EncoderForVersion() 方法逻辑如下:

// k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.gofunc (f CodecFactory) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {return f.CodecForVersions(nil, decoder, nil, gv)}func (f CodecFactory) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {return f.CodecForVersions(encoder, nil, gv, nil)}func (f CodecFactory) CodecForVersions(encoder runtime.Encoder, decoder runtime.Decoder, encode runtime.GroupVersioner, decode runtime.GroupVersioner) runtime.Codec {// TODO: these are for backcompat, remove them in the futureif encode == nil {encode = runtime.DisabledGroupVersioner}if decode == nil {decode = runtime.InternalGroupVersioner}return versioning.NewDefaultingCodecForScheme(f.scheme, encoder, decoder, encode, decode)}// staging/src/k8s.io/apimachinery/pkg/runtime/serializer/versioning/versioning.gofunc NewDefaultingCodecForScheme(scheme *runtime.Scheme,encoder runtime.Encoder,decoder runtime.Decoder,encodeVersion runtime.GroupVersioner,decodeVersion runtime.GroupVersioner,) runtime.Codec {return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion, scheme.Name())}func NewCodec(encoder runtime.Encoder,decoder runtime.Decoder,convertor runtime.ObjectConvertor,creater runtime.ObjectCreater,typer runtime.ObjectTyper,defaulter runtime.ObjectDefaulter,encodeVersion runtime.GroupVersioner,decodeVersion runtime.GroupVersioner,originalSchemeName string,) runtime.Codec {internal := &codec{encoder: encoder,decoder: decoder,convertor: convertor,creater: creater,typer: typer,defaulter: defaulter,encodeVersion: encodeVersion,decodeVersion: decodeVersion,identifier: identifier(encodeVersion, encoder),originalSchemeName: originalSchemeName,}return internal}
目前先我们写到这里,在下一篇文章中我们继续来介绍 codec 的序列化和反序列化过程。
文章转载自TA码字,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




