Cliente Java oficial dois do Kubernetes: problemas de serialização e desserialização

Bem-vindo ao meu GitHub

https://github.com/zq2599/blog_demos

Cenário de problema

Este artigo é o segundo capítulo do "Cliente Java oficial do Kubernetes". Antes de entrar no capítulo de codificação real, há um problema que exige que todos tenham compreensão suficiente para evitar o gasto de energia para lidar com esse tipo de problema no combate real subsequente. Vamos ver o que é. problema:

  1. SpringBoot é uma estrutura de aplicativo comumente usada. Os aplicativos da série "Kubernetes Official Java Client" são todos baseados na versão SpringBoot-2.3.1;

  2. A figura a seguir é o documento oficial do SpringBoot-2.3.1.RELEASE. A caixa vermelha indica que a biblioteca de processamento JSON padrão é Jackson:
    Insira a descrição da imagem aqui

  3. Vendo isso, você tem um pressentimento sinistro: o cliente Java oficial do K8S é o Google. Quando se trata de processamento JSON, seu próprio Gson será preferido?

  4. V1HTTPGetAction.java é uma estrutura de dados comumente usada em clientes java. É usada para encapsular os parâmetros relacionados à solicitação http. Vamos dar uma olhada no código-fonte. Conforme mostrado na figura abaixo, ele realmente usa as anotações de Gson:
    Insira a descrição da imagem aqui

  5. A classe IntOrString mencionada na figura acima deve ser focada e tem uma ampla gama de usos. Abra seu código-fonte conforme mostrado na figura abaixo. Anote o código na caixa vermelha 2. O problema mencionado mais tarde vem deste:
    Insira a descrição da imagem aqui

  • Resumo: A classe de processamento JSON padrão do SpringBoot é Jackson. O Bean no cliente K8S java oficial usa anotações Gson quando se trata de serialização e desserialização relacionadas a JSON. Portanto, a instância Bean acima envolve processamento JSON no SpringBoot. Neste momento, pode haver problemas (só podemos dizer isso neste momento), por exemplo, o objeto retornado por RestController será convertido para JSON por Jackson;

Problema recorrente

  1. Aqui está um projeto SpringBoot para demonstrar esse problema (o projeto é denominado OutsideclusterApplication, que será explicado em detalhes no próximo artigo). O código a seguir é uma resposta de interface http. Pode-se ver que quando a instância V1PodList é retornada como uma interface, ela será convertida em JSON por SpringBoot usando Jackson a parte dianteira:
@RequestMapping(value = "/hello")
    public V1PodList hello() throws Exception {
    
    
        // 存放K8S的config文件的全路径
        String kubeConfigPath = "/Users/zhaoqin/temp/202007/05/config";

        // 以config作为入参创建的client对象,可以访问到K8S的API Server
        ApiClient client = ClientBuilder
                .kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath)))
                .build();

        Configuration.setDefaultApiClient(client);

        CoreV1Api api = new CoreV1Api();

        // 调用客户端API取得所有pod信息
        V1PodList v1PodList = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null);

        return v1PodList;
    }
  1. O código acima é executado. Quando o navegador acessa a interface, o console emite o seguinte erro. O método IntOrString.getStrValue é o parágrafo que vimos antes. IntOrString na verdade armazena dados internos, mas Jackson executa seu getStrValue método:
    Insira a descrição da imagem aqui

  2. Quanto ao motivo de Jackson executar o método getStrValue, o comprimento do motivo não será expandido aqui. Basta mencionar que na classe BeanPropertyWriter do cliente Java, a lógica do método de seleção é mostrada na figura a seguir. A caixa vermelha mostra a lógica de determinação. Aqui, o método getStrValue acerta isso Lógica, se você tentar observar com um ponto de interrupção na caixa vermelha, verá que existem muitos métodos que atendem a esta condição:
    Insira a descrição da imagem aqui

Ideias para resolver o problema

Aqui, tenho duas ideias para resolver o problema:

  1. Permita que Jackson chame o método correto durante a serialização. Tome IntOrString como exemplo. Se os dados int forem armazenados internamente neste momento, seu método getIntValue deve ser executado;
  2. A anotação Gson é usada em Bean, que se destina a usar Gson para lidar com operações de serialização e desserialização, portanto, a serialização e a desserialização são alteradas para processamento Gson;
  • Para as duas ideias acima, escolhi a segunda, afinal a primeira é muito difícil ...

Resolva o problema

  1. O problema não é difícil de resolver, primeiro olhe o documento oficial SpringBoot-2.3.1.RELEASE:
    Insira a descrição da imagem aqui

  2. Combinado com documentos oficiais, temos que fazer duas coisas:

  • Em primeiro lugar, há Gson no caminho de classe, ele já está lá, porque o cliente Java oficial K8S contará com Gson;
  • Em segundo lugar, não inclua Jackson no caminho de classe. Para conseguir isso, precisamos fazer o seguinte para excluir a dependência de spring-boot-starter-web (por que não excluir diretamente a biblioteca de Jackson? Você pode executar o comando mvn dependency: tree para examinar mais de perto a árvore de dependência , Você verá que a dependência de jackson não é um único relacionamento):
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
		<exclusions>
			<exclusion>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-starter-json</artifactId>
			</exclusion>
		</exclusions>
</dependency>
  1. É recomendado que você execute o comando mvn dependency: tree para examinar mais de perto a árvore de dependências de todo o projeto para garantir que todas as dependências de jackson foram removidas;
  2. Execute o projeto acima novamente, conforme mostrado na figura abaixo, o servidor não reporta mais um erro e os dados retornados na página são normais:
    Insira a descrição da imagem aqui

Cenas usando Jackson

  • Embora o método acima seja viável, nem todos os projetos podem aderir ao Gson e desistir de Jackson. Para projetos que usam Jackson, evite que Jackson participe da serialização e desserialização de beans de cliente java oficial K8S. Pegue o código do controlador que aparece acima como Por exemplo, não retorne a instância V1PodList diretamente. Você pode escolher serializá-la em uma string JSON com Gson primeiro e, em seguida, retornar a string para o front end ou pode definir seu próprio objeto VO, converter a instância V1PodList em um objeto VO e depois retornar;

  • Neste ponto, os problemas aos quais devemos prestar atenção antes de usar o cliente Java oficial do K8S foram resolvidos.A seguir, vamos entrar no maravilhoso capítulo prático e experimentar as ferramentas cuidadosamente preparadas pelo oficial do Kubernetes para programadores Java;

Acho que você gosta

Origin blog.csdn.net/boling_cavalry/article/details/107503695
Recomendado
Clasificación