Este artigo é baseado no discurso "Financial Technology Go Microservices" proferido por Liu Yi, engenheiro sênior de P&D do Founder Securities Financial Technology Engineering Institute, no "Cloud Native✖️Microservice Architecture and Technical Practice in the AI Era" CloudWeGo Technology Salon Evento de Pequim realizado em Pequim em 30 de março de 2024. Compilado de "Prática de Construção".
Visão geral: Este artigo apresentará em detalhes a experiência prática do Founder Securities Financial Technology Engineering Institute na construção de microsserviços nativos da nuvem. O compartilhamento inclui três aspectos:
- Trabalho de governança de microsserviços
- Trabalho de observabilidade de microsserviços
- Os recursos acima de gerenciamento de interface de microsserviços são unificados e integrados à plataforma de desenvolvimento Quark do Founder.
Introdução à prática de construção de microsserviços de Founder Securities
No início de 2023, lançamos a construção de um sistema de microsserviços, em que a central de cadastro utiliza ZooKeeper , e os frameworks de aplicação Web e RPC utilizam Hertz e Kitex da CloudWeGo respectivamente .
Atualmente, entramos na área de águas profundas de construção de microsserviços, que envolve principalmente governança de microsserviços , capacidades de observabilidade , gerenciamento de interface e outros trabalhos relacionados. A seguir apresentaremos em detalhes os conceitos e princípios de implementação.
Desenvolvimento de capacidade de governança de microsserviços
conceito
Na arquitetura de microsserviços, à medida que o volume de negócios aumenta gradualmente, o número de serviços também aumentará gradualmente. Com base neste contexto, à medida que o negócio se desenvolve, será cada vez mais difícil gerir e controlar os serviços. O papel da governação de serviços é resolver uma série de problemas causados pela divisão de serviços para que os serviços possam funcionar de forma mais estável. fornece registro e descoberta de serviço, balanceamento de carga, disjuntor de serviço, degradação de serviço, limitação de corrente de serviço, etc. As funções de tempo limite, repetição e limitação de corrente do lado do servidor fornecidas pela plataforma Quark são todas baseadas nos recursos relacionados do Kitex . O centro de registro usado atualmente é o ZooKeeper (abreviado como zk), portanto, a configuração dinâmica relacionada também é implementada com a ajuda. de zk, por meio de Grave a configuração em zk para notificar o servidor e o cliente para concluir a ativação das funções relacionadas.
introduzir
-
controle de fluxo
A granularidade do controle de fluxo é o nível de serviço Conforme mostrado na figura abaixo, o serviço pode lidar com até 1.000 solicitações por segundo, e as solicitações excessivas serão encerradas diretamente:
-
Tentar novamente a configuração
A granularidade da configuração de nova tentativa é no nível do método, que é usado para configurar como tentar novamente quando o serviço atual falha ao fazer uma solicitação a um método do serviço especificado:
-
Configuração de tempo limite
A granularidade da configuração do tempo limite está no nível do método, que é usado para configurar o tempo máximo que o serviço atual leva para solicitar um método do serviço especificado. Quando esse valor for excedido, o serviço atual será desconectado: consulte a configuração. descrição das funções específicas de cada configuração.
Princípios e detalhes de implementação
Tanto o lado do servidor quanto o lado do cliente completam a injeção dinâmica de configurações relevantes, estendendo o conjunto do Kitex .
lado do servidor
Configure o servidor Kitex através do seguinte código:
server.WithSuite(zooKeeperServer.NewSuite("Kitex-server", zooKeeperClient))
Dentre eles, será retornada uma instância de suíte, e será incluída zooKeeperServer.NewSuite("Kitex-server", zooKeeperClient)
a configuração do limitador injetada no servidor : Options
func (s *zooKeeperServerSuite) Options() []server.Option {
opts := make([]server.Option, 0, 2)
// WithLimiter实现中,在zk中注册了监听器,每当数据变化,动态更新Limiter的相关配置,以达到限流目的
opts = append(opts, WithLimiter(s.service, s.zooKeeperClient, s.opts))
return opts
}
Com base no conteúdo acima, pode-se descobrir que apenas limitadores são configurados por padrão no conjunto do lado do servidor. A estrutura Kitex atualmente suporta apenas dois tipos de limitadores:
- Limitador de conexões (limita o número máximo de conexões)
- Limitador de Qps (limite máximo de qps)
Ao usar zk como centro de registro, ambos podem ser ajustados dinamicamente por meio da configuração. Após as alterações, os valores de configuração são obtidos por meio do ouvinte do zk:
// zk数据变化时的回调方法
onChangeCallback := func(restoreDefault bool, data string, parser zooKeeper.ConfigParser) {
lc := &limiter.LimiterConfig{}
if !restoreDefault && data != "" {
err := parser.Decode(data, lc)
if err != nil {
klog.Warnf("[zooKeeper] %s server zooKeeper config: unmarshal data %s failed: %s, skip...", dest, data, err)
return
}
}
// 将zk中的数据动态更新到配置中
opt.MaxConnections = int(lc.ConnectionLimit)
opt.MaxQPS = int(lc.QPSLimit)
u := updater.Load()
if u == nil {
klog.Warnf("[zooKeeper] %s server zooKeeper limiter config failed as the updater is empty", dest)
return
}
if !u.(limit.Updater).UpdateLimit(opt) {
klog.Warnf("[zooKeeper] %s server zooKeeper limiter config: data %s may do not take affect", dest, data)
}
}
// path,对于limiter,其值为:/KitexConfig/{ServiceName}/limit
zooKeeperClient.RegisterConfigCallback(context.Background(), path, uniqueID, onChangeCallback)
lado do cliente
Semelhante ao lado do servidor, o lado do cliente também possui a mesma configuração:
bizService.NewClient("Kitex-client",
client.WithSuite(zooKeeperclient.NewSuite("Kitex-server", "Kitex-client", zooKeeperClient)))
A suíte do lado do cliente contém as seguintes opções:
func (s *zooKeeperClientSuite) Options() []client.Option {
opts := make([]client.Option, 0, 7)
opts = append(opts, WithRetryPolicy(s.service, s.client, s.zooKeeperClient, s.opts)...)
opts = append(opts, WithRPCTimeout(s.service, s.client, s.zooKeeperClient, s.opts)...)
opts = append(opts, WithCircuitBreaker(s.service, s.client, s.zooKeeperClient, s.opts)...)
return opts
}
Ou seja, o cliente suporta três configurações dinâmicas: nova tentativa, tempo limite e disjuntor. O processamento relevante é feito através do método de retorno de chamada do cliente zk para obter o efeito de atualização dinâmica.
Notas adicionais sobre configuração de tempo limite
Para o tempo limite, a implementação específica do seu método de configuração é a seguinte:
func WithRPCTimeout(dest, src string, zooKeeperClient zooKeeper.Client, opts utils.Options) []client.Option {
// ...
return []client.Option{
client.WithTimeoutProvider(initRPCTimeoutContainer(path, uid, dest, zooKeeperClient)),
client.WithCloseCallbacks(func() error {
// cancel the configuration listener when client is closed.
zooKeeperClient.DeregisterConfig(path, uid)
return nil
}),
}
}
client.WithTimeoutProvider
Por fim, a configuração específica relacionada ao timeout é concluída chamando o método fornecido pelo Kitex . Para tempos limite, existem os seguintes métodos de configuração diferentes:
func WithRPCTimeout(d time.Duration) Option {
// ...
}
func WithConnectTimeout(d time.Duration) Option {
// ...
}
func WithTimeoutProvider(p rpcinfo.TimeoutProvider) Option {
// ...
}
Entre eles, WithTimeoutProvider
o tempo limite definido será substituído WithRPCTimeout
pelo valor definido de , portanto, se ou WithConnectTimeout
for chamado ao criar o cliente Kitex, a configuração dinâmica não terá efeito.WithRPCTimeout
WithConnectTimeout
Instruções de configuração
tempo esgotado
Nó zk correspondente:/kitexConfig/{ClientName}/{ServiceName}/rpc_timeout
O formato de configuração escrito é o seguinte:
{
"*": {
"conn_timeout_ms": 100,
"rpc_timeout_ms": 800
},
"GetDemoInfo": {
"rpc_timeout_ms": 300
},
"GetDemoInfo3": {
"rpc_timeout_ms": 300
}
}
Significado do campo : tempo máximo de espera para estabelecer uma nova conexão; tempo máximo para uma chamada RPC; conn_timeout_ms
rpc_timeout_ms
Tentar novamente
Nó zk correspondente:/kitexConfig/{ClientName}/{ServiceName}/retry
O formato de configuração escrito é o seguinte:
{
"GetDemoInfo": {
"enable": true,
"type": 0,
"failure_policy": {
"stop_policy": {
"max_retry_times": 2,
"max_duration_ms": 9000,
"cb_policy": {
"error_rate": 0.1
}
}
}
},
"GetDemoInfo5": {
"enable": true,
"type": 0,
"failure_policy": {
"stop_policy": {
"max_retry_times": 2,
"max_duration_ms": 9000,
"cb_policy": {
"error_rate": 0.1
}
}
}
}
}
Significado do campo
Itens de configuração | valor padrão | ilustrar | limite |
---|---|---|---|
max_retry_times | 2 | O número máximo de novas tentativas, excluindo a primeira solicitação. Se configurado como 0, significa parar de tentar novamente. | Valores legais: [0-5] |
duração_máx_ms | 0 | O tempo máximo cumulativo decorrido, incluindo o tempo decorrido para a primeira solicitação com falha e a solicitação de nova tentativa. Se o tempo decorrido atingir o limite, as tentativas subsequentes serão interrompidas. 0 significa sem limite. Nota: Se configurado, este item de configuração deverá ser maior que o tempo limite da solicitação. | |
taxa de erro | 10% | Limite de taxa de erro do disjuntor de nova tentativa. Se a taxa de erro de solicitação no nível do método exceder o limite, as novas tentativas serão interrompidas. | Valores legais: (0-30%] |
Limitando
Esta configuração é uma configuração global para o serviço, portanto, o caminho do nó zk contém apenas serviceName:/kitexConfig/{ServiceName}/limit
O formato de configuração escrito é o seguinte:
{
"qps_limit": 100
}
Desenvolvimento de capacidade de observabilidade de microsserviços
conceito
A construção da observabilidade do serviço refere-se ao estabelecimento e melhoria de monitoramento, registro, rastreamento e outras ferramentas e tecnologias em sistemas distribuídos, a fim de compreender de forma abrangente e oportuna o status operacional e os indicadores de desempenho do sistema.
Uma ferramenta completa de observação pode trazer muitos benefícios aos sistemas empresariais:
- Capacidade de detectar e resolver problemas em tempo hábil;
- Permitir que a equipe tenha uma compreensão mais clara da operação geral e das interações internas do sistema;
- Pode compreender o status da carga, a utilização de recursos e as mudanças de tendência do sistema para apoiar o planejamento de capacidade e a otimização de recursos;
- Ao registrar os logs de operação do sistema e rastreamentos de solicitações por meio do sistema de log e rastreamento, comportamentos operacionais do usuário, solicitações anormais e eventos de segurança podem ser rastreados e analisados para melhorar a segurança e a confiabilidade do sistema.
introduzir
Os detalhes do serviço são usados para exibir a operação geral do próprio serviço, incluindo indicadores dourados de monitoramento (QPS, latência e taxa de erro), SLO e informações relacionadas ao tempo de execução, etc.:
O diagrama de topologia é usado para mostrar as dependências upstream e downstream entre serviços:
Os dados da cadeia de chamadas contêm informações detalhadas sobre cada chamada entre serviços:
Princípios e detalhes de implementação
Atualmente, o cliente OpenTelemetry foi integrado ao código do modelo e os serviços Hertz e Kitex gerados possuem recursos de relatório de dados observáveis (Métricas + Rastreamento) por padrão.
Para informações detalhadas, consulte: kitex-contrib/obs-opentelemetry e hertz-contrib/obs-opentelemetry
OpenTelemetry (OTel) é uma estrutura de observabilidade de código aberto que permite que equipes de desenvolvimento gerem, processem e transmitam dados de telemetria em um formato único e unificado. Foi desenvolvido pela Cloud Native Computing Foundation (CNCF) para fornecer protocolos e ferramentas padrão para coletar e enviar métricas, logs e rastreamentos para plataformas de monitoramento. OpenTelemetry fornece SDKs, APIs e ferramentas independentes de fornecedor. OpenTelemetry está rapidamente se tornando o padrão dominante de dados de telemetria de observabilidade para aplicativos nativos da nuvem. A adoção do OpenTelemetry é fundamental para organizações que desejam estar prontas para atender às necessidades futuras de dados sem ficarem presas a um fornecedor específico ou limitadas por sua tecnologia legada.
Vestígio
O rastreamento fornece uma visão completa de todo o ciclo de vida, desde o recebimento da solicitação até a conclusão.
Após receber a solicitação, o serviço permite o rastreamento do link a partir de meta informações (Kitex) ou cabeçalho http (Hertz). Se não houver informações de rastreamento nas metainformações ou no cabeçalho HTTP, o novo rastreamento de link será ativado automaticamente. As informações do link são passadas dentro do processo de serviço por meio do contexto.
Método de acesso:
// for Hertz
tracer, cfg := hertztracing.NewServerTracer()
h := server.Default(tracer)
h.Use(hertztracing.ServerMiddleware(cfg))
// for Kitex
svr := echo.NewServer(new(DemoImpl),
server.WithSuite(tracing.NewServerSuite()),
server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}),)
As informações de rastreamento são relatadas ao OpenTelemetry Collector e depois transmitidas de forma transparente ao Jaeger. Informações relacionadas ao link podem ser consultadas no Jaeger.
Fornece uma impressora de log unificada fzlog, que imprime informações relacionadas ao rastreamento por padrão.
{
"file": "get_repositories.go:33",
"func": "gitlab.fzzqft.com/ifte-quark/quark-api/biz/service.(*GetRepositoriesService).Run",
"level": "info",
"msg": "GetRepositoriesService Run req: page:1 limit:10 service_name:\"kitex\"",
"span_id": "aa26bab58cdf6806",
"time": "2024-04-23 15:59:40.609",
"trace_flags": "01",
"trace_id": "f714dbe2a96b1882dfc4b81909e55643"
}
Depois que os logs são coletados e processados, as informações de log relevantes de todo o link podem ser consultadas na plataforma de log . trace_id
Métricas
Métricas são dados importantes que medem o desempenho e o comportamento do sistema, como taxa de solicitação, tempo de resposta, taxa de erro, etc. As métricas são normalmente coletadas, agregadas e visualizadas para monitorar a integridade do sistema e realizar análises de tendências.
Atualmente, cada serviço reporta seus próprios dados de Métricas e os armazena uniformemente no Prometheus/VictoriaMetrics e, por fim, utiliza grafana para formar um painel de monitoramento.
A seguir, são usados três indicadores comuns de descrição de serviço: QPS, tempo de solicitação e taxa de erro para demonstrar como usar os dados de métricas relatados pelo serviço.
-
QPS: Com base na definição de QPS, precisamos apenas obter o número de solicitações em tempo real para calcular o QPS.
http_server_duration_count
O valor nos dados relatados é consistente com o número de solicitações, portanto esta métrica pode ser usada para completar o cálculo de QPS. QPS.sum(rate(http_server_duration_count{service_name="$service_name"}[$__rate_interval]))
cópia deNo promQL acima, a função rate é usada para calcular a taxa de crescimento de uma determinada métrica dentro de um período de tempo especificado, e o resultado final é o número médio de solicitações dentro do período de tempo especificado.
-
Consumo de tempo de solicitação: Por se tratar de um dado estatístico, optamos aqui por utilizar a média para representar o consumo de tempo das solicitações de serviço. O consumo de tempo médio é obtido pelo consumo de tempo total de todas as solicitações no período de tempo especificado ➗O número de solicitações. solicitações no período de tempo especificado:
sum(rate(http_server_duration_sum{service_name="$service_name"}[$__rate_interval])) by (application) / sum(rate(http_server_duration_count{service_name="$service_name"}[$__rate_interval])) by (application)
cópia de -
Taxa de erro: primeiro filtre o número de solicitações erradas e divida pelo número total de solicitações para obter a taxa de erro
round((1 - (sum(rate(http_server_duration_count{service_name="$service_name",http_status_code=~"^(2|3).*"} [$__interval]))/sum(rate(http_server_duration_count{service_name="$service_name"}[$__interval])))), 0.0001)
cópia de
Topologia
As dependências gerais entre serviços são exibidas por meio dos dados métricos mencionados na agregação. Os dados relatados contêm service_name
informações , source
e as informações upstream e downstream do serviço podem ser obtidas target
por meio do operador PromSQL .sum
Construção de capacidade de gerenciamento de interface de microsserviço
conceito
-
IDL
Interface Description Language (IDL) é uma linguagem de computador usada para descrever a interface de componentes de software. IDL descreve interfaces de forma independente da linguagem de programação, permitindo que objetos executados em diferentes plataformas e programas escritos em diferentes linguagens se comuniquem entre si.
-
Gerenciamento de interface
Os serviços Kitex (RPC) são todos implementados com base em IDL. A plataforma de gerenciamento de interface fornece principalmente uma plataforma de interface para gerenciar os produtos IDL de serviços RPC, tornando mais fácil para os desenvolvedores gerenciar e chamar interfaces RPC.
-
Teste de interface
O serviço Kitex (RPC) está inacessível para teste. Os usuários da plataforma de teste de interface resolvem esse problema para facilitar o teste e o desenvolvimento iniciando solicitações RPC por meio da plataforma para concluir a depuração.
introduzir
- Plataforma de gerenciamento de interface (veja a imagem para método de operação)
- Plataforma de teste de interface (interface de depuração Kitex (RPC))
Princípios e detalhes de implementação
-
Gerenciamento de interface
Anteriormente, usávamos um armazém independente com gitlabci para gerenciar os produtos IDL do serviço Kitex : durante o uso real, havia os seguintes pontos problemáticos:
- O chamador precisa obter o endereço, filial ou número de versão do armazém do produto IDL através de uma pequena janela (chat privado)
- O método de prestação de serviços precisa prestar atenção tanto ao armazém do projeto de serviço quanto ao armazém do produto correspondente.
- O Gitlabci depende fortemente do runner, e novos grupos precisam ser configurados pelo administrador antes de poderem ser usados.
- Não é possível vincular-se profundamente ao processo CICD existente
Para resolver os problemas e pontos problemáticos acima, uma plataforma de gerenciamento de interface foi projetada e desenvolvida.
Quando o serviço é construído e empacotado, o processo de atualização do produto IDL é acionado. A plataforma detectará automaticamente o tipo de serviço e gerará o produto IDL correspondente e o enviará ao armazém independente do gitlab. Os usuários também podem criar ou atualizar manualmente produtos IDL na plataforma. O chamador só precisa copiar e executar o comando import path para obter a versão correspondente da dependência de serviço.
-
O teste de interface é implementado com base na chamada de generalização de mapeamento JSON do Kitex PB. O usuário seleciona o serviço e a interface correspondentes na plataforma, e a plataforma analisa automaticamente o arquivo IDL correspondente e fornece os parâmetros de solicitação padrão (formato json). Após o envio da solicitação, a plataforma inicia uma solicitação RPC ao serviço alvo por meio de uma chamada generalizada e retorna o resultado.
resumo
O atual sistema de microsserviços já pode atender à maioria das necessidades técnicas, mas planejamos ir mais longe no sistema nativo da nuvem:
- A governança de serviços depende de recursos de malha de serviço nativa da nuvem (ServiceMesh) para gerenciar o tráfego, ao mesmo tempo que incorpora o tráfego leste-oeste de outras estruturas de aplicativos.
- Observabilidade, OpenTelemetry é um conjunto de soluções independentes de linguagem e estrutura de aplicação. Por meio de semântica unificada, planeja incorporar os sistemas Java Web (Springboot) e RPC (Dubbo).
- Gerenciamento de interface, no futuro está planejado o gerenciamento unificado de interfaces RPC e HTTP e a geração automática de casos de uso de interface.
atividades recentes
Usuários corporativos e desenvolvedores estão sinceramente convidados a participar do CloudWeGo Technology Salon. O evento será realizado em Xangai em 25 de maio de 2024 (sábado) , convidando colegas técnicos para discutir como as empresas podem construir uma arquitetura de microsserviços nativa da nuvem para apoiar a rápida iteração e desenvolvimento de produtos sob a onda de xAI nativa da nuvem . Digitalize o código QR na imagem para se inscrever imediatamente, nos vemos lá!
Os recursos piratas de "Celebrating More Than Years 2" foram carregados no npm, fazendo com que o npmmirror tivesse que suspender o serviço unpkg da Microsoft na China fez as malas coletivamente e foi para os Estados Unidos, envolvendo centenas de pessoas . biblioteca de visualização front-end e o conhecido projeto de código aberto ECharts do Baidu - "indo para o mar" para apoiar os golpistas de peixes usaram o TeamViewer para transferir 3,98 milhões! O que os fornecedores de desktop remoto devem fazer? Zhou Hongyi: Não resta muito tempo para o Google. Recomenda-se que todos os produtos sejam de código aberto. Um ex-funcionário de uma conhecida empresa de código aberto deu a notícia: Após ser desafiado por seus subordinados, o líder técnico ficou furioso e. demitiu a funcionária grávida. O Google mostrou como executar o ChromeOS em uma máquina virtual Android. Por favor, me dê alguns conselhos: qual é o papel do time.sleep(6) aqui? A Microsoft responde aos rumores de que a equipe de IA da China está "fazendo as malas para os Estados Unidos" Comentários do People's Daily Online sobre a cobrança semelhante a matryoshka do software de escritório: Somente resolvendo ativamente "conjuntos" podemos ter um futuro