Runtime: Pergunta: Suporte de serialização a partir do .Net Core 1.0

Criado em 1 mar. 2016  ·  38Comentários  ·  Fonte: dotnet/runtime

Olá a todos,
Ouvi dizer que o suporte para serialização foi descontinuado no .Net Core 1.0, pois não é viável para plataforma cruzada. (Parafraseando de memória) O que isso significa em termos práticos? Minhas bases de código que usam os métodos Serialize e Deserialize de BinaryFormatter serão completamente descontinuadas e terei que converter minha base de código para dizer, protobuf-net? Ou eu entendi mal?
Obrigado,
-Sam

area-Serialization question

Comentários muito úteis

Você quer que as pessoas realmente usem o .NET Core ou isso é apenas uma perda de tempo como o Silverlight? Se você deseja que as pessoas realmente usem o .NET Core, faça-o funcionar. Se as pessoas precisam de serialização, crie-a - sem conversa fiada! Essas são as pessoas que realmente usam seu produto, e a opinião delas vale muito mais do que a sabedoria coletiva de cada funcionário da Microsoft. Você vê que essas pessoas estão, ao contrário da Microsoft, realmente construindo coisas de missão crítica no .NET e se você quiser que o .NET Core seja qualquer coisa, você tem que parar de quebrar sua utilidade. Ninguém pediu para você abandonar o .NET para fazer uma reescrita completa, você poderia apenas portar o framework .NET completo com o tempo. Você já teria terminado.

Todos 38 comentários

Olá @joshfree , sim, infelizmente foi esse o documento que causou a confusão. Com as sugestões lá, JSON.NET faz serialização json, protobuf-net faz serialização binária e datacontractserializer faz serialização xml. O problema com isso é se eu quero fazer a serialização binária. Embora protobuf-net seja uma ótima biblioteca, ela é limitada. No repositório Protobuf-nets, os tipos suportados são:
classes personalizadas que:
são marcados como contrato de dados
tem um construtor sem parâmetros
para Silverlight: são públicos
muitos primitivos comuns etc
matrizes de dimensão única: T []
List / IList
Dicionário / IDictionary
qualquer tipo que implemente IEnumerable e tenha um método Add (T)
No passado, isso funcionava bem, pois o formatador binário sempre existiu, mas não será mais o caso? Qual é a maneira recomendada de serialização binária de tipos não suportados por protobuf-net? Construir nós mesmos?
Ainda sou muito novato em todas essas tecnologias, então posso estar perdendo completamente o foco em algo.

Além disso, nenhum deles pode serializar exceções de forma confiável (e manter todos os dados relevantes), conforme necessário, por exemplo, em computação distribuída (Azure ...).

O ponto obstáculo para caras como os caras do Orleans IIRC.

Olá @SamuelCox , como a orientação de portabilidade @joshfree apontou, nós (equipe de serialização) não temos planos de trazer o serializador binário para .NET Core. Sem o .NET Remoting e o conceito de AppDomain no .NET Core, o serializador binário é muito menos útil. Considere outros serializadores no .NET Core, como DataContractSerializer (DCS), DataContractJsonSerializer (DCJS) e XmlSerializer, que são e continuarão a ter suporte no .NET Core. Claro, você também pode considerar serializadores de terceiros criados no .NET Core. Talvez eu deva fazer a pergunta - você está procurando particularmente por um serializador que tenha carga útil serializada binária (se sim, por quê) ou você apenas procura um serializador que possa serializar / desserializar os tipos de seu interesse? Temos tentado muito oferecer suporte à serialização da maioria dos tipos de .NET com DCS, DCJS e XmlSerializer. Sinta-se à vontade para nos informar se você tiver algum problema específico de que esses serializadores não funcionam para você.

@cdrnet e @ RichiCoder1 , obrigado por seus comentários. Houve um problema aberto dotnet / coreclr # 2715 para a discussão de serialização de exceção. Por favor, adicione seu feedback lá. Eu concordo que é importante ser capaz de serializar exceções em um sistema distribuído. Atualmente, sem ISerializable no .NET Core, simplesmente não podemos serializar exceções como fazemos no .NET framework completo.

Olá, @zhenlan , Talvez devesse ter mencionado originalmente que o principal motivo pelo qual desejaria o binaryformatter é para (des) serializar exceções e classes personalizadas que contenham exceções.

O principal caso de uso são sistemas distribuídos, serializando algum objeto em um array de bytes para que eu possa enviá-lo por tcp / ip. Percebi que é provavelmente mais comum serializar o objeto para JSON via JSON.NET, por exemplo, converter essa string em uma matriz de bytes, enviar por tcp / ip e reverter todo o processo uma vez na outra extremidade. Mas isso tem muito mais sobrecarga do que apenas serializar em uma matriz de bytes e desserializar de uma matriz de bytes para o objeto que você deseja.

Obrigado @SamuelCox pelo esclarecimento. Acho que entendo sua preocupação agora. A serialização binária é um sistema fechado. Eu recomendo que você considere outra serialização baseada em um padrão mais aberto, como Xml ou JSON. Você pode não precisar disso hoje, mas oferece mais flexibilidade no caso de você precisar oferecer suporte à serialização entre plataformas diferentes ou com linguagens de programação / scripts diferentes no futuro. Não tenho certeza do tamanho de seus dados, mas se o tamanho da carga útil for realmente uma preocupação, você pode considerar a compactação de dados, que é um recurso integrado para muitos servidores hoje em dia.

Eu estava pensando mais na sobrecarga de desempenho do que em qualquer outra coisa. Parece um monte de operações perdidas em comparação com a serialização e desserialização diretamente de objetos para o binário e vice-versa. Acho que estou feliz por encerrar isso agora, pois pelo menos recebi esclarecimentos. Ainda acho que há uma lacuna entre o 4.6 e o ​​núcleo 1.0 que está sendo aberta aqui, mas entendo por quê.

Um pouco tarde para a conversa, mas aqui estão meus dois centavos:

Acho que seria um erro acreditar que a utilidade do BinaryFormatter se limita a .NET remoting e AppDomains. O que diferencia o (obsoleto) BinaryFormatter de seus equivalentes mais recentes é sua capacidade absoluta de serializar os objetos .NET mais exóticos, incluindo encerramentos, subtipos e gráficos cíclicos. Nenhum dos outros serializadores listados no segmento atual é capaz de fazer tudo isso. Não é por acaso que muitas estruturas distribuídas de ponta, incluindo projetos da Microsoft como Prajna e Mobius (também conhecido como SparkCLR), dependem do BinaryFormatter para funcionar. Isso não é exclusivo do mundo .NET: o Spark usa o antigo e lento serializador binário Java para serializar encerramentos.

Existem outros serializadores (formato não binário) que replicam os recursos do BinaryFormatter, incluindo nossa própria biblioteca FsPickler usada pela estrutura mbrace. No entanto, o CoreCLR descontinuou muitas APIs principais, a ponto de acreditar que portar a biblioteca para o CoreCLR é um esforço impraticável.

De uma perspectiva de negócios, seria ótimo ver o CoreCLR se tornando um concorrente de plataforma cruzada viável para JVM no domínio de computação distribuída / big data. Isso não pode acontecer sem que a plataforma ofereça suporte de serialização confiável para POCOs e fechamentos (binários ou não).

Você quer que as pessoas realmente usem o .NET Core ou isso é apenas uma perda de tempo como o Silverlight? Se você deseja que as pessoas realmente usem o .NET Core, faça-o funcionar. Se as pessoas precisam de serialização, crie-a - sem conversa fiada! Essas são as pessoas que realmente usam seu produto, e a opinião delas vale muito mais do que a sabedoria coletiva de cada funcionário da Microsoft. Você vê que essas pessoas estão, ao contrário da Microsoft, realmente construindo coisas de missão crítica no .NET e se você quiser que o .NET Core seja qualquer coisa, você tem que parar de quebrar sua utilidade. Ninguém pediu para você abandonar o .NET para fazer uma reescrita completa, você poderia apenas portar o framework .NET completo com o tempo. Você já teria terminado.

Fwiw, CSLA .NET depende da serialização de fidelidade total porque se baseia no conceito de objetos móveis.

Quando o Silverlight apareceu e não tinha BinaryFormatter ou NetDataContractSerializer, _and_ tinha todas essas limitações de reflexão desagradáveis, acabamos implementando nosso próprio serializador que usa reflexão mínima e não depende de BF ou NDCS.

Em um mundo pós-Silverlight, o problema permanece, porque BF / NDCS não estão disponíveis de forma confiável em UWP, WinRT, .NET Core, etc.

Portanto, acho que há um argumento a ser feito de que um serializador de fidelidade total _deve_ existir, mas ele só é realmente útil (pelo menos imo) se existir em todas as várias encarnações do .NET.

@rockfordlhotka @opinionmachine @eiriktsarpalis Fico feliz em ouvir mais pessoas sentirem o mesmo, embora eu ache que seria mais produtivo se fosse dito um pouco mais educadamente @opinionmachine , mas cada um com o seu. Quando este problema for resolvido, imagino que a equipe corefx não o esteja mais monitorando. Aconselho você a corrigir suas dúvidas no dotnet / coreclr # 2715, conforme mencionado por @forki

Eu teria que concordar que descartar a serialização (assim como os appdomains) foi uma ideia terrível. Eu realmente não acho que essa decisão foi bem pensada.

No entanto, o que realmente me motiva é que a MS não lançou o código necessário para dar suporte a appdomains, etc e deixou para a comunidade fazer o que quiser com ele.

Dado que o coreclr é supostamente a versão "servidor" do .net, muitos recursos do servidor foram deixados no chão.

Caso em questão: foi decidido deixar StackTrace / StackFrame fora do corefx porque foi "mal utilizado" por alguns desenvolvedores e porque raramente era usado (de acordo com a MS). Eu acredito que eles caíram em si sobre isso (depois de uma tonelada de reação), mas quero dizer realmente? Quem pensa nessas coisas?

Pelo que vale a pena, estou realmente muito feliz com o núcleo .net e acho que é um grande passo para .net, as melhorias de desempenho são brilhantes, ele ainda tem praticamente todos os recursos que me interessam e é multiplataforma. Este é realmente o único problema que tenho com ele. Há muito valor em descartar recursos quando apropriado, basta olhar para o sucesso do go com sua abordagem minimalista. Não que eu esteja dizendo que .net deve ser tão minimalista quanto possível, isso seria ridículo, eu pessoalmente discordo de um design minimalista, MAS o que estou tentando dizer é que o MS não deve ser vilipendiado por descartar certos recursos.

@SamuelCox , obrigado! :-)

E, para reiterar, APIs estão faltando no .NET Core por muitos motivos. Algumas dessas lacunas podem ser corrigidas facilmente (e nós as estamos corrigindo); alguns são mais difíceis de consertar. Mas queremos ouvir de você sobre os problemas que você está enfrentando (como todo este conjunto de threads sobre serialização) e queremos encontrar uma maneira de desbloquear seus cenários.

A serialização binária de gráficos de objetos arbitrários entre versões de uma única estrutura é difícil; em diferentes estruturas é ainda mais difícil. E por "difícil" não quero dizer que seja difícil para nós fazer o trabalho. Quero dizer que tem implicações de longo alcance para outros objetivos da plataforma (objetivos que acho que todos nós compartilhamos): segurança, desempenho, confiabilidade.

Json.NET + TypeNameHandling.All + PreserveReferencesHandling.All + MemberSerialization.Fields leva você quase até lá. Não há FormatterServices.GetUninitializedObject, no entanto, um construtor precisa estar disponível.

Não há FormatterServices.GetUninitializedObject

Este é o problema principal, eu acho - estruturas de serialização baseadas em reflexão externa podem levar você longe, mas esta API específica precisa estar lá para permitir que essas estruturas sejam escritas. Minha recomendação para a equipe CoreCLR seria adicionar esta API de volta.

Em algum momento, a comunidade .NET (comercial ou não) terá que parar de depender da Microsoft segurando sua mão o tempo todo. Se existe um requisito tão grande para isso, e já se sabe há muito tempo que não está disponível, por que não houve nenhuma atividade da comunidade para fornecer uma alternativa? Json.NET é uma alternativa da comunidade e usamos isso o tempo todo. Heck, o código-fonte está até disponível na fonte de referência

Parece funcionar para outras plataformas e tenho certeza que funciona muito bem no .NET ... a meu ver, esta é uma excelente oportunidade para criar um projeto (que parece haver uma demanda) e obter no início de preencher esse vazio com alternativa (s) da comunidade

@thecodejunkie adoraríamos, mas ainda precisaríamos do tempo de execução para expor as APIs adequadas para que isso acontecesse.

Para sua informação: isso funciona no .NET Core: Type appDomainType = Type.GetType("System.AppDomain"); . E sim, permite que você faça muitas coisas ....

Só para dizer que melhoramos a capacidade de resposta do servidor front-end em 30%, reduzimos de 12 núcleos em carga máxima para 2 núcleos em carga máxima, diminuímos o tamanho do cache redis de 1,7 Gb para 350 MB em geral, reduzimos nossa hospedagem Azure em 20% (bit mais realmente)

Você adivinhou BinaryFormatter!

Estávamos usando netdatacontractserializer

Eu vim aqui procurando respostas para .Net 4.6.1 sendo muito mais lento com BinaryFormatter.

É meu entendimento que essas APIs voltarão (serialização). Embora não seja ideal e tenha alguns problemas por ser frágil, isso pelo menos deve permitir que o código existente continue em execução.

também é importante projetar outro serializador de objeto simples para a estrutura principal, um que também seja leve, mas seja mais resistente a máquinas cruzadas e, potencialmente, a várias versões.

Existem também problemas de segurança além da fragilidade.

@blowdart WRT security, você quer dizer coisas como esta https://blog.scrt.ch/2016/05/12/net-serialiception/?

Sim, esse é o tipo de coisa. Qualquer formato de serialização que inclua o tipo dentro dele é perigoso, como o Java está descobrindo este ano. Fiquei incrivelmente feliz quando abandonamos a serialização binária porque removemos uma classe inteira de vulnerabilidades.

@migueldeicaza @blowdart @SamuelCox
Os serializadores são necessários não apenas para enviar coisas, mas até mesmo no proc.
Os serializadores binários, quando feitos adequadamente, superam todo o heap de objeto nativo quando se trata de armazenar 10s de milhões de objetos em processo.
Veja isso:
https://www.infoq.com/articles/Big-Memory-Part-2

As APIs de serialização são absolutamente necessárias para a programação sã do cluster.
É extremamente inconveniente teletransportar instâncias de objeto CLR -> texto -> CLR, é uma sobrecarga enorme.
Talvez não seja um erro retirar BinaryFormatter, pois é MUITO lento e os datagramas são enormes, mas
esse era o único serializador no mercado, além do NFX.Slim, que suportava a semântica de serialização completa do CLR.
Veja os gráficos detalhados de velocidade e tamanho:
http://aumcode.github.io/serbench/

ISerializable com a família [OnSer / Deser] FAZ muito sentido para teletransporte na plataforma.
Não é obrigatório, assim como na antiga NET. Por que não ficar com ele?
Suporta pelo menos em coleções complexas (ou seja, Dicionário), não é nada difícil.

Fazer com que todos usem JSON é uma ideia absolutamente má, pois é vezes mais lento que o serializador binário (não BinaryFormatter).
Parece que todo mundo está criando aplicativos semelhantes ao Twitter sem lógica de negócios?

O @itadapter tem um

@ RichiCoder1
Sim, claro. Como pode ser visto nos gráficos abaixo, isto é, JIL é o serilizador JSON mais rápido, porém nenhum dos serializadores baseados em texto pode tocar nos binários. Protobuf é muito rápido às custas de sua incapacidade de suportar polimorfismo verdadeiro e gráficos complexos.

Tudo o que estou dizendo é:

  • Os serializadores binários são sempre mais eficientes para objetos de domínio de negócios, especialmente quando você tem muitos dados numéricos
  • Os serializadores, em geral, são necessários NÃO SÓ para mover dados entre sistemas, mas até mesmo dentro do processo, como mostra a abordagem do Big Memory. Não é uma abordagem típica, mas faz muito sentido prático (ou seja, caches e travessias de gráficos sociais na memória)
  • "Teletransporte" é a técnica semelhante ao MS Remoting, que honestamente foi malfeita. Remoting em geral quando feito da maneira certa (sem complexidade horrível) é MUITO, MUITO útil em sistemas de cluster. Usamos essa abordagem o tempo todo e a programação é MUITO mais fácil com objetos nativos - quando você pode pegar objetos DOMAIN e apenas enviá-los para outro método como estão, seja nesta máquina ou em uma máquina adjacente no rack

Comparativos de mercado de uma "pessoa típica", mostrando serializadores populares:
http://aumcode.github.io/serbench/Specimens_Typical_Person/web/overview-charts.htm

Caso alguém neste tópico não saiba, o serializador binário incluindo ISerializable etc. foi disponibilizado no corefx
https://github.com/dotnet/corefx/tree/master/src/System.Runtime.Serialization.Formatters

@zhenlan Parte do trabalho .NetStandard2.0, presumo?

@ RichiCoder1 Sim, correto.

@zhenlan é ótimo!

@zhenlan Não consigo encontrar o Atributo Serializável disponível na visualização do Standard. Eu estou apenas perdendo isso?

@justinhelgerson deveria estar lá.

Você instalou 2.0 Preview1 SDK conforme instruído na postagem do blog de anúncio ?

Depois de criar um projeto .NET Core, você pode garantir que o arquivo .csproj tenha <TargetFramework>netstandard2.0</TargetFramework> se você criou uma biblioteca de classes ou <TargetFramework>netcoreapp2.0</TargetFramework> se criou um aplicativo de console?

BTW, uma vez que muitas pessoas neste segmento têm interesse no serializador binário, você pode estar interessado na discussão em dotnet / corefx # 19119, que é sobre como reduzir [Serializable] para .NET Core 2.0. Informe-nos caso tenha algum comentário.

@zhenlan Muito obrigado pela sua resposta rápida. Eu instalei a visualização via NuGet, mas não atualizei manualmente meu arquivo .csproj. Isso funcionou! Vou ler sobre a redução e fornecer informações se isso impactar nosso caso de uso.

@justinhelgerson , as mudanças de

Esta página foi útil?
0 / 5 - 0 avaliações