Fundador Securities-tecnología financiera práctica de construcción de microservicios nativos en la nube

Este artículo se basa en el discurso "Financial Technology Go Microservices" pronunciado por Liu Yi, ingeniero senior de I+D del Founder Securities Financial Technology Engineering Institute, en el salón de tecnología CloudWeGo "Cloud Native✖️Arquitectura de microservicios y práctica técnica en la era de la IA". Evento de Beijing celebrado en Beijing el 30 de marzo de 2024. Compilado de "Construction Practice".

Descripción general: este artículo presentará en detalle la experiencia práctica del Founder Securities Financial Technology Engineering Institute en la construcción de microservicios nativos de la nube. El intercambio incluye tres aspectos:

  1. Trabajo de gobernanza de microservicios
  2. Trabajo de observabilidad de microservicios.
  3. Las capacidades anteriores de gestión de interfaces de microservicios están unificadas e integradas en la plataforma de desarrollo Quark de Founder.

Introducción a la práctica de la construcción de microservicios de Founder Securities.

A principios de 2023, lanzamos la construcción de un sistema de microservicio, en el que el centro de registro utiliza ZooKeeper , y los marcos de aplicaciones web y RPC utilizan Hertz y Kitex de CloudWeGo respectivamente .    

En la actualidad, hemos entrado en el área profunda de la construcción de microservicios, que implica principalmente gobernanza de microservicios , capacidades de observabilidad , gestión de interfaces y otros trabajos relacionados. A continuación se presentarán los conceptos y principios de implementación en detalle.

Desarrollo de capacidades de gobernanza de microservicios

concepto

Bajo la arquitectura de microservicios, a medida que el volumen de negocios aumenta gradualmente, la cantidad de servicios también aumentará gradualmente. Con base en estos antecedentes, a medida que el negocio se desarrolle, será cada vez más difícil administrar y controlar los servicios. La función de la gobernanza del servicio es resolver una serie de problemas causados ​​por la división del servicio para que los servicios puedan funcionar de manera más estable. proporciona registro y descubrimiento de servicios, equilibrio de carga, disyuntor de servicio, degradación del servicio, limitación de corriente del servicio, etc. Las funciones de tiempo de espera, reintento y limitación de corriente del lado del servidor proporcionadas por la plataforma Quark se basan en las capacidades relacionadas de Kitex . El centro de registro utilizado actualmente es ZooKeeper (abreviado como zk), por lo que la configuración dinámica relacionada también se implementa con la ayuda. de zk, escriba la configuración en zk para notificar al servidor y al cliente que completen la activación de las funciones relacionadas.  

introducir

  1. control de flujo

    La granularidad del control de flujo es el nivel de servicio. Como se muestra en la figura siguiente, el servicio puede manejar hasta 1000 solicitudes por segundo y las solicitudes excesivas se cerrarán directamente: límite_tasa_huaxing

  2. Reintentar configuración

    La granularidad de la configuración de reintento es el nivel de método, que se utiliza para configurar cómo reintentar cuando el servicio actual no puede realizar una solicitud a un método del servicio especificado: huaxing_retry

  3. Configuración de tiempo de espera

    La granularidad de la configuración del tiempo de espera está a nivel de método, que se utiliza para configurar el tiempo máximo que tarda el servicio actual en solicitar un método del servicio especificado. Cuando se excede este valor, el servicio actual se desconectará: consulte la configuración. descripción de las funciones específicas de cada configuración. huaxing_timeout 

Principios y detalles de implementación.

Tanto el lado del servidor como el del cliente completan la inyección dinámica de configuraciones relevantes ampliando la suite de Kitex .  

lado del servidor

Configure el servidor Kitex a través del siguiente código:

server.WithSuite(zooKeeperServer.NewSuite("Kitex-server", zooKeeperClient))
Copiar

Entre ellos, zooKeeperServer.NewSuite("Kitex-server", zooKeeperClient)se devolverá una instancia de la suite y se incluirá la configuración del limitador inyectada en el 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
}
Copiar

Según el contenido anterior, se puede encontrar que solo los limitadores están configurados de forma predeterminada en la suite del lado del servidor. El marco Kitex  actualmente solo admite dos tipos de limitadores:

  1. Limitador de conexiones (limita el número máximo de conexiones)
  2. Limitador de Qps (limita los qps máximos)

Cuando se utiliza zk como centro de registro, ambos se pueden ajustar dinámicamente mediante la configuración. Después de los cambios, los valores de configuración se obtienen a través del oyente de 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)
Copiar

lado del cliente

Al igual que en el lado del servidor, el lado del cliente también tiene la misma configuración:

bizService.NewClient("Kitex-client",
client.WithSuite(zooKeeperclient.NewSuite("Kitex-server", "Kitex-client", zooKeeperClient)))
Copiar

La suite del lado del cliente contiene las siguientes opciones:

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
}
Copiar

Es decir, el cliente admite tres configuraciones dinámicas: reintento, tiempo de espera y disyuntor. El procesamiento relevante se realiza mediante el método de devolución de llamada del cliente zk para lograr el efecto de actualización dinámica.

Notas adicionales sobre la configuración del tiempo de espera

Para el tiempo de espera, la implementación específica de su método de configuración es la siguiente:

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
        }),
    }
}
Copiar

client.WithTimeoutProviderFinalmente, la configuración específica relacionada con el tiempo de espera se completa llamando al método proporcionado por Kitex . Para los tiempos de espera, existen los siguientes métodos de configuración diferentes:

func WithRPCTimeout(d time.Duration) Option {
    // ...
}

func WithConnectTimeout(d time.Duration) Option {
    // ...
}

func WithTimeoutProvider(p rpcinfo.TimeoutProvider) Option {
    // ...
}
Copiar

Entre ellos, WithTimeoutProviderel tiempo de espera establecido se sobrescribirá WithRPCTimeoutcon el valor establecido de , por lo que si WithConnectTimeoutse llama a WithRPCTimeouto al crear el cliente Kitex, WithConnectTimeoutla configuración dinámica no tendrá efecto.

Instrucciones de configuración

se acabó el tiempo

Nodo zk correspondiente:/kitexConfig/{ClientName}/{ServiceName}/rpc_timeout

El formato de configuración escrito es el siguiente:

{
  "*": {
    "conn_timeout_ms": 100,
    "rpc_timeout_ms": 800
  },
  "GetDemoInfo": {
    "rpc_timeout_ms": 300
  },
  "GetDemoInfo3": {
    "rpc_timeout_ms": 300
  }
}
Copiar

Significado del campo : el tiempo máximo de espera para establecer una nueva conexión: el tiempo máximo para una llamada rpc; conn_timeout_ms rpc_timeout_ms

Rever

Nodo zk correspondiente:/kitexConfig/{ClientName}/{ServiceName}/retry

El formato de configuración escrito es el siguiente:

{
  "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
        }
      }
    }
  }
}
Copiar

Significado del campo

Elementos de configuración valor por defecto ilustrar límite
max_retry_times 2 El número máximo de reintentos, excluyendo la primera solicitud. Si se configura en 0, significa dejar de reintentar. Valores legales: [0-5]
max_duration_ms 0 El tiempo máximo acumulado transcurrido, incluido el tiempo transcurrido para la primera solicitud fallida y la solicitud de reintento. Si el tiempo transcurrido alcanza el límite, se detendrán los reintentos posteriores. 0 significa sin límite. Nota: Si está configurado, este elemento de configuración debe ser mayor que el tiempo de espera de la solicitud.  
Tasa de error 10% Reintentar el umbral de tasa de error del disyuntor; si la tasa de error de solicitud a nivel de método excede el umbral, se detendrán los reintentos. Valores legales: (0-30%]

Limitando

Esta configuración es una configuración global para el servicio, por lo que la ruta del nodo zk solo contiene el nombre del servicio:/kitexConfig/{ServiceName}/limit

El formato de configuración escrito es el siguiente:

{
  "qps_limit": 100
}
Copiar

Creación de capacidad de observabilidad de microservicios

concepto

La construcción de observabilidad del servicio se refiere al establecimiento y mejora de monitoreo, registro, seguimiento y otras herramientas y tecnologías en sistemas distribuidos para comprender de manera integral y oportuna el estado operativo y los indicadores de rendimiento del sistema.

Una herramienta de observación completa puede aportar muchos beneficios a los sistemas empresariales:

  1. Capacidad para detectar y resolver problemas de manera oportuna;
  2. Permitir que el equipo tenga una comprensión más clara del funcionamiento general y las interacciones internas del sistema;
  3. Puede comprender el estado de la carga, la utilización de recursos y los cambios de tendencias del sistema para respaldar la planificación de la capacidad y la optimización de los recursos;
  4. Al registrar los registros de operación del sistema y los seguimientos de solicitudes a través del sistema de registro y seguimiento, se pueden rastrear y analizar los comportamientos de operación del usuario, las solicitudes anormales y los eventos de seguridad para mejorar la seguridad y confiabilidad del sistema.

introducir

Los detalles del servicio se utilizan para mostrar el funcionamiento general del servicio en sí, incluidos los indicadores de monitoreo dorados (QPS, latencia y tasa de errores), SLO e información relacionada con el tiempo de ejecución, etc.: huaxing_grafana

El diagrama de topología se utiliza para mostrar las dependencias ascendentes y descendentes entre servicios: topología_huaxing

Los datos de la cadena de llamadas contienen información detallada sobre cada llamada entre servicios: huaxing_trace

Principios y detalles de implementación.

hotel_huaxing

Actualmente, el cliente OpenTelemetry se ha integrado en el código de la plantilla y los servicios Hertz y Kitex generados tienen capacidades de generación de informes de datos observables (Métricas + Seguimiento) de forma predeterminada.    

Para obtener información detallada, consulte: kitex-contrib/obs-opentelemetry  y hertz-contrib/obs-opentelemetry 

OpenTelemetry  (OTel) es un marco de observabilidad de código abierto que permite a los equipos de desarrollo generar, procesar y transmitir datos de telemetría en un formato único y unificado. Fue desarrollado por Cloud Native Computing Foundation (CNCF) para proporcionar protocolos y herramientas estándar para recopilar y enviar métricas, registros y seguimientos a plataformas de monitoreo. OpenTelemetry proporciona SDK, API y herramientas independientes del proveedor. OpenTelemetry se está convirtiendo rápidamente en el estándar de datos de telemetría de observabilidad dominante para aplicaciones nativas de la nube. La adopción de OpenTelemetry es fundamental para las organizaciones que desean estar preparadas para satisfacer las necesidades futuras de datos sin estar atadas a un proveedor específico o limitadas por su tecnología heredada.

Rastro

El seguimiento proporciona una imagen completa de todo el ciclo de vida desde la recepción de la solicitud hasta su finalización.

Después de recibir la solicitud, el servicio habilita el seguimiento de enlaces desde metainformación (Kitex) o encabezado http (Hertz). Si no hay información de seguimiento en la metainformación o en el encabezado HTTP, el seguimiento de nuevos enlaces se habilitará automáticamente. La información del enlace se pasa dentro del proceso de servicio a través del contexto.

Método de acceso:

// for Hertz
tracer, cfg := hertztracing.NewServerTracer()
h := server.Default(tracer)
h.Use(hertztracing.ServerMiddleware(cfg))
Copiar
// for Kitex
svr := echo.NewServer(new(DemoImpl),
    server.WithSuite(tracing.NewServerSuite()),
    server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}),)
Copiar

La información de seguimiento se envía a OpenTelemetry Collector y luego se transmite de forma transparente a Jaeger. La información relacionada con el enlace se puede consultar en Jaeger.

Proporciona una impresora de registros unificada fzlog, que imprime información relacionada con el seguimiento de forma predeterminada.

{
  "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"
}
Copiar

Una vez recopilados y procesados ​​​​los registros, la información de registro relevante de todo el enlace se puede consultar en la plataforma de registros . trace_id 

Métrica

Las métricas son datos clave que miden el rendimiento y el comportamiento del sistema, como la tasa de solicitudes, el tiempo de respuesta, la tasa de errores, etc. Por lo general, las métricas se recopilan, agregan y visualizan para monitorear el estado del sistema y realizar análisis de tendencias.

Actualmente, cada servicio informa sus propios datos de métricas y los almacena de manera uniforme en Prometheus/VictoriaMetrics, y finalmente usa grafana para formar un panel de monitoreo.

A continuación se utilizan tres indicadores comunes de descripción de servicios: QPS, tiempo de solicitud y tasa de error para demostrar cómo utilizar los datos de métricas informados por el servicio.

  • QPS: según la definición de QPS, solo necesitamos obtener la cantidad de solicitudes en tiempo real para calcular QPS. http_server_duration_count El valor en los datos informados es consistente con la cantidad de solicitudes, por lo que esta métrica se puede usar para completar el cálculo de. QPS.

    sum(rate(http_server_duration_count{service_name="$service_name"}[$__rate_interval]))
    
    Copiar

    En el promQL anterior, la función de tasa se utiliza para calcular la tasa de crecimiento de una determinada métrica dentro de un período de tiempo específico, y el resultado final es el número promedio de solicitudes dentro del período de tiempo especificado.

  • Consumo de tiempo de solicitud: dado que son datos estadísticos, aquí elegimos utilizar el promedio para representar el consumo de tiempo de las solicitudes de servicio. El consumo de tiempo promedio se obtiene por el consumo de tiempo total de todas las solicitudes en el período de tiempo especificado ➗El número de. solicitudes en el período de tiempo 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)
    
    Copiar
  • Tasa de error: primero filtre la cantidad de solicitudes erróneas y divida por la cantidad total de solicitudes para obtener la tasa de error

    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)
    
    Copiar

Topología

Las dependencias generales entre servicios se muestran a través de los datos métricos mencionados en la agregación. Los datos informados contienen service_nameinformación , sourcey la información ascendente y descendente del servicio se puede obtener targeta través del operador PromSQL .sum

Creación de capacidades de gestión de interfaces de microservicios

concepto

  • idl

    El lenguaje de descripción de interfaz (IDL) es un lenguaje informático que se utiliza para describir la interfaz de los componentes de software. IDL describe interfaces de forma independiente del lenguaje de programación, lo que permite que los objetos que se ejecutan en diferentes plataformas y programas escritos en diferentes lenguajes se comuniquen entre sí.

  • Gestión de interfaz

    Todos los servicios Kitex (RPC) se implementan en base a IDL. La plataforma de administración de interfaces proporciona principalmente una plataforma de interfaz para administrar los productos IDL de los servicios RPC, lo que facilita a los desarrolladores administrar y llamar a las interfaces RPC.

  • Pruebas de interfaz

    No se puede acceder al servicio Kitex (RPC) para realizar pruebas. Los usuarios de la plataforma de prueba de interfaz resuelven este problema para facilitar las pruebas y el desarrollo iniciando solicitudes RPC a través de la plataforma para completar la depuración.

introducir

  • Plataforma de gestión de interfaz (ver imagen para conocer el método de operación) interfaz_huaxing_1 interfaz_huaxing_2 interfaz_huaxing_3
  • Plataforma de prueba de interfaz (depuración de interfaz Kitex (RPC)) prueba_interfaz_huaxing

Principios y detalles de implementación.

  • Gestión de interfaz

    Anteriormente, utilizamos un almacén independiente con gitlabci para administrar los productos IDL del servicio Kitex : durante el uso real, surgieron los siguientes puntos débiles:   interfaz_huaxing_impl 

    1. La persona que llama debe obtener la dirección, sucursal o número de versión del almacén de productos IDL a través de una pequeña ventana (chat privado)
    2. El método de prestación de servicios debe prestar atención tanto al almacén del proyecto de servicio como al almacén de producto correspondiente.
    3. Gitlabci depende en gran medida del corredor y el administrador debe configurar los nuevos grupos antes de que puedan usarse.
    4. No se puede vincular profundamente al proceso CICD existente

    Para resolver los problemas y puntos débiles anteriores, se diseñó y desarrolló una plataforma de gestión de interfaz. plataforma_interfaz_huaxing

    Cuando el servicio se crea y empaqueta, se activa el proceso de actualización del producto IDL. La plataforma detectará automáticamente el tipo de servicio, generará el producto IDL correspondiente y lo enviará al almacén independiente de gitlab. Los usuarios también pueden crear o actualizar manualmente productos IDL en la plataforma. La persona que llama solo necesita copiar y ejecutar el comando de ruta de importación para obtener la versión correspondiente de la dependencia del servicio.

  • La prueba de interfaz se implementa en base a la llamada de generalización de mapeo JSON de Kitex PB. El usuario selecciona el servicio y la interfaz correspondientes en la plataforma, y ​​la plataforma analiza automáticamente el archivo IDL correspondiente y proporciona los parámetros de solicitud predeterminados (formato json). Después de enviar la solicitud, la plataforma inicia una solicitud RPC al servicio de destino mediante una llamada generalizada y devuelve el resultado. huaxing_interface_test_logic 

resumen

El sistema de microservicio actual ya puede satisfacer la mayoría de las necesidades técnicas, pero planeamos ir más allá con el sistema nativo de la nube:

  1. La gobernanza del servicio se basa en capacidades de malla de servicios nativa de la nube (ServiceMesh) para gestionar el tráfico, al mismo tiempo que incorpora el tráfico de este a oeste desde otros marcos de aplicaciones.
  2. Observabilidad, OpenTelemetry es un conjunto de soluciones que son independientes del lenguaje y el marco de la aplicación. A través de una semántica unificada, planea incorporar los sistemas Java Web (Springboot) y RPC (Dubbo).
  3. Gestión de interfaces, en el futuro está previsto gestionar de forma unificada las interfaces RPC y HTTP y generar automáticamente casos de uso de interfaces.

actividades recientes

Los usuarios y desarrolladores empresariales están sinceramente invitados a participar en el Salón de Tecnología CloudWeGo . El evento se llevará a cabo en Shanghai el 25 de mayo de 2024 (sábado) , e invitará a colegas técnicos a discutir cómo las empresas pueden construir una arquitectura de microservicios nativa de la nube para respaldar la rápida iteración y el desarrollo de productos bajo la ola de xAI nativa de la nube . Escanea el código QR en la imagen para registrarte inmediatamente, ¡nos vemos allí! 

 

Los recursos pirateados de "Celebrating More Than Years 2" se cargaron en npm, lo que provocó que npmmirror tuviera que suspender el servicio unpkg. El equipo de inteligencia artificial de Microsoft en China empacó colectivamente y se fue a los Estados Unidos, involucrando a cientos de personas. Biblioteca de visualización frontal y el conocido proyecto de código abierto ECharts de Baidu: "ir al mar" para respaldar a Fish. ¡ Los estafadores utilizaron TeamViewer para transferir 3,98 millones! ¿Qué deberían hacer los proveedores de escritorio remoto? Zhou Hongyi: No queda mucho tiempo para que Google recomiende que todos los productos sean de código abierto. Un ex empleado de una conocida empresa de código abierto dio la noticia: después de ser desafiado por sus subordinados, el líder técnico se enfureció. Despidió a la empleada embarazada. Google mostró cómo ejecutar ChromeOS en una máquina virtual de Android. Por favor, dame un consejo, ¿qué papel juega aquí time.sleep(6)? Microsoft responde a los rumores de que el equipo de IA de China está "haciendo las maletas para Estados Unidos" El People's Daily Online comenta sobre la carga tipo matrioska del software de oficina: Sólo resolviendo activamente los "conjuntos" podremos tener un futuro
{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/4843764/blog/11181511
Recomendado
Clasificación