Servicio de bayoneta——Basado en la práctica de expansión del sistema de inspección frontal|Tecnología Dewu

1. Antecedentes

La experiencia es una de las palabras clave comerciales de Dewu. Para el desarrollo front-end, mejorar la experiencia del usuario es una de las tareas más importantes.

La plataforma front-end de Dewu cuenta actualmente con sistemas de inspección, plataformas de monitoreo y otros medios para garantizar el funcionamiento estable de las páginas en línea, pero aún existen algunos problemas en el "monitoreo de puntos ciegos", y las inspecciones y el monitoreo son métodos posteriores a la alarma. Para garantizar que las páginas estén en línea Podemos obtener una cierta garantía de experiencia de usuario por adelantado, combinado con los objetivos estratégicos de la empresa, decidimos desarrollar un servicio de detección de páginas H5, que se utiliza para detectar previamente las páginas que están a punto de ser lanzado, y exponer los posibles problemas de las páginas con anticipación para retroalimentar al desarrollo/operación correspondiente, llamamos a este servicio: "Experiencia Checkpoint".

Este artículo comienza con la práctica de desarrollo del servicio de "bayoneta de experiencia" y presenta la estructura y el diseño del sistema de inspección Dewu, con la esperanza de proporcionar algún valor de aprendizaje y referencia para los socios de desarrollo involucrados en la construcción de la estabilidad.

2 Estándares de cuantificación de la experiencia del usuario

Cuando tratamos de cuantificar los problemas que afectan la experiencia del usuario, debemos pensar en las siguientes dos preguntas principales:

¿Qué afecta la experiencia del usuario?

Hemos adquirido una comprensión profunda de los factores que afectan la experiencia del usuario a través de un rico soporte de datos y experiencia práctica. Basándonos en la recopilación de comentarios de problemas en línea anteriores y en la experiencia de desarrollo, dividimos aproximadamente los problemas de experiencia en dos niveles:

Nivel P0: estos problemas afectan seriamente la velocidad de carga de la página o implican riesgos de seguridad, por ejemplo, la página contiene imágenes/recursos multimedia grandes y la página contiene información de privacidad personal;

Nivel P1: estos problemas pueden tener un impacto potencial en la experiencia del usuario, por ejemplo, hay solicitudes de interfaz con un tiempo de respuesta superior a 300ms en la página.

¿Cómo detectar y cuantificar el problema?

Una vez que hemos definido y calificado nuestros problemas de experiencia, debemos establecer los mecanismos adecuados para detectarlos. Para el servicio de punto de control, podemos seguir los siguientes pasos para cuantificar el problema, convertirlo en un código de detección ejecutable y generar un informe de detección correspondiente a través del servicio de punto de control para que lo utilice la persona que llama:

  1. Identificar métricas y métricas: Primero, necesitamos identificar métricas y métricas para cuantificar los problemas de experiencia. Por ejemplo, para el problema de la velocidad de solicitud de la interfaz, el tiempo de respuesta de la interfaz se puede usar como un indicador y se pueden establecer ciertos estándares al mismo tiempo, como exceder un umbral de tiempo específico se considera un problema.

  2. Escritura de scripts de automatización: en función de indicadores y estándares, podemos escribir scripts de automatización para simular que los usuarios realizan operaciones relacionadas en un navegador sin cabeza, como cargar páginas, hacer clic en botones, enviar solicitudes, etc. Estos scripts realizarán la medición del rendimiento y la detección de problemas en función de las métricas establecidas.

  3. Ejecutar pruebas con un navegador sin interfaz: podemos ejecutar scripts automatizados en un navegador sin interfaz para simular el comportamiento del usuario y recopilar los datos de rendimiento correspondientes.

  4. Análisis de resultados y generación de informes: a través de los datos de rendimiento recopilados, podemos realizar análisis de resultados y convertir problemas y datos relacionados en informes de prueba. El informe puede incluir una descripción detallada del problema, el nivel del problema, indicadores de desempeño y datos relevantes.

Proporcionar a la persona que llama: Finalmente, a través del servicio de punto de control, podemos proporcionar el informe de detección generado a la persona que llama. La persona que llama puede realizar las optimizaciones y mejoras correspondientes en función de los problemas y los datos del informe para mejorar la experiencia del usuario.

Dicho mecanismo puede ayudarnos a detectar y cuantificar automáticamente los problemas de experiencia y proporcionar un código de detección ejecutable e informes relacionados. De esta manera, podemos identificar y resolver problemas de manera más efectiva, y proporcionar datos precisos para que los equipos de desarrollo los optimicen.

Los siguientes son los casos de detección que hemos resuelto que deben implementarse:

1.png

Después de recopilar los casos específicos que afectan la experiencia del usuario, es necesario determinar el plan de desarrollo específico.Dado que el servicio de bayoneta y el sistema de inspección de la plataforma frontal Dewu tienen muchas superposiciones técnicas, decidimos utilizar la arquitectura de inspección existente para integrar el El "punto de control de experiencia" está integrado en el sistema de inspección existente, lo que puede ahorrar mucho tiempo de desarrollo.

3 Infraestructura del sistema de inspección

El objetivo del programa del sistema de inspección se resume en una oración: obtener regularmente la lista de direcciones de página que se detectarán de la fuente de datos y luego realizar la detección por lotes y generar informes.

Para satisfacer las necesidades personalizadas en diferentes escenarios, el sistema de inspección abstrae tres clases base de inspectores, y cada escena hereda las clases base para realizar los requisitos de personalización.

3.1 Clase base de patrulla

1. DataProviderBase (clase base de proveedor de datos):

dataSlim(): Simplifica los datos redundantes;

fetchData(): Obtenga datos remotos, procese y devuelva la lista de direcciones URL de las páginas que se detectarán;

isSkipTime(): se usa para establecer condiciones y omitir tareas de tiempo bajo ciertas condiciones;

Schedule (): establece el intervalo de ejecución de la tarea programada;

2.png

2. PageInspectorBase (clase base del inspector de páginas):

check(): Entrada del verificador, utilizada para abrir la página de detección especificada e inicializar el monitoreo de varios recursos;

injectRequestHeaders(): Inyectar cookies, tokens, etc. requeridos por la solicitud de la interfaz de la página;

urlCheck (): verificación de dirección URL;

onRequest(): Supervisar las solicitudes de página;

onResponse(): monitorear la respuesta de la página;

onPageError(): Supervisar errores de página;

3.png

3. DataReporterBase (clase base de informe de datos):

buildReporter(): genera un informe de detección basado en la información de error recopilada;

feishuNotify(): envía el informe generado al grupo de notificación especificado a través de Feishu;

getHTMLReporterUrl(): genera un archivo html estático para el informe de acuerdo con la plantilla ejs y lo carga, y devuelve la dirección del informe en línea;

4.png

Podemos comparar visualmente estas tres clases base con tres departamentos con diferentes divisiones del trabajo en un restaurante, lo que lo hace más fácil de entender:

La recepción del hotel se encarga de recibir los pedidos proporcionados por los clientes, la cocina elabora y prepara los platos de acuerdo a los pedidos, y los meseros brindan las comidas preparadas a los clientes.

DataProviderBase (clase base de proveedor de datos): Responsable del sondeo regular para recibir la lista de páginas a detectar proporcionadas externamente. Este componente es similar a la recepción de un restaurante, recibiendo los pedidos de los clientes. Es responsable de obtener la lista de páginas a detectar desde el exterior y pasar estas páginas al detector para su detección.

PageInspectorBase (clase base del inspector de páginas): detecta cada URL en la lista de páginas una por una y detecta problemas potenciales en la página. Similar al proceso de cortar ingredientes, cocinar y cargar platos según el orden, este componente se encarga de detectar las URL en la lista de páginas a detectar una por una y detectar problemas en cada página. Puede usar una serie de métodos y reglas de detección para determinar si hay problemas potenciales con la página.

DataReporterBase (clase base de informes de datos): después de clasificar los problemas recopilados por la detección, se envía el informe. Al igual que el camarero que proporciona comidas preparadas a los clientes, este componente es responsable de clasificar y resumir los problemas detectados y generar los informes correspondientes. Los informes pueden incluir información como una descripción del problema, la gravedad y las URL de las páginas relacionadas. Luego, los informes se pueden enviar a las partes interesadas relevantes, como desarrollo u operaciones.

3.2 Patrulla

Sobre la base de las tres clases base anteriores, se desarrollan diferentes inspectores (inspectores) de acuerdo con diferentes escenarios de inspección. Cada inspector incluye tres subclases que heredan las tres clases base anteriores, y las subclases que heredan los inspectores de clase base. El inspector se da cuenta de sus propios requisitos individuales. anulando/extendiendo el método de la clase base. El siguiente es un ejemplo de inspector minimalista:

// data-provider.ts
export class DataProvider extends DataProviderBase {
  // 实现特定的页面列表获取逻辑
  async fetchData(args) {
    return await axios.get('https://xxx.xxx').then(res => res.data.urlList)
  }
  // 每隔15分钟获取一次待检测列表
  async schedule() {
    return [{cron: '*/15 * * * *',args: {}}]
  }
}

// page-inspector.ts
export class PageInspector extends PageInspectorBase {
  async onPageOpen(page, reporter: PageReporter, data) {
    const pageTitle = await page.evaluate('window.document.title')
    console.log('这里可以获取到页面title', pageTitle)
  }
}

// data-reporter.ts
export class DataReporter extends DataReporterBase {
  async beforeFeishuNotify(data: InspectorReportBase) {
    console.log('在飞书通知前做点什么', data)
    return data
  }
}


3.3 Programa principal de inspección

En el sistema de inspección, la tarea de detección de cada página es una tarea asíncrona independiente, y la clasificación y envío de cada informe de detección también es una tarea asíncrona independiente. Para facilitar la gestión y el mantenimiento de estas tareas asíncronas y el almacenamiento y envío de mensajes de tareas, el sistema de inspección utiliza Redis combinado con Bull como herramienta de gestión de tareas asíncronas del sistema de inspección.

Redis es una base de datos en memoria que proporciona capacidades de acceso y almacenamiento de datos de alto rendimiento.

Bull es una biblioteca de colas de tareas basada en Redis, que proporciona las funciones de programación, ejecución y entrega de mensajes de tareas.

Con el inspector y las capacidades de gestión de tareas asincrónicas, el trabajo principal del programa principal es el siguiente:

  1. Definir tareas: use Bull para crear dos colas de tareas, page_queue se usa para almacenar "tareas de detección de página", reporter_queue se usa para almacenar "tareas de generación de informes".

  2. Tarea de producción: En el sistema de inspección, el productor (programa principal) de la tarea de detección de páginas y la tarea de generación de informes es responsable de agregar la tarea a la cola correspondiente. Cuando el inspector necesita realizar la detección de páginas, el productor agrega la tarea de detección de páginas a page_queue; cuando necesita generar un informe, el productor agrega la tarea de generación de informes a reporter_queue.

  3. Tarea de consumo: El consumidor de tareas (programa principal) en el sistema de inspección es responsable de obtener y ejecutar tareas de la cola de tareas. Una tarea de detección tendrá >=1 tarea de detección de página, y el inspector de página PageInspector presentado anteriormente ejecutará la verificación de página y, a continuación, almacene el informe de detección en Redis. Cuando se detectan todas las páginas de la tarea de detección, el DataReporter del inspector crea y consume la tarea reporter_queue.

servicio de 4 bayonetas

Después de presentar el sistema de inspección, veamos cómo integrar el servicio de bayoneta en el sistema de autoinspección.

La función principal del servicio de punto de control se puede resumir en una oración: acceder a la arquitectura existente del sistema de inspección, exponer una interfaz remota al exterior, proporcionar a la persona que llama la interfaz la capacidad de detectar activamente la página y luego enviar la informe de detección a la persona que llama.

Compare la diferencia entre el sistema de inspección existente y el servicio de bayoneta:

8.png

A partir de la introducción de la arquitectura del sistema de inspección anterior y el análisis de la tabla anterior, podemos ver que el desarrollo del servicio de bayoneta consiste en personalizar e implementar un dispositivo de inspección basado en la arquitectura del dispositivo de inspección del sistema de inspección.

4.1 Secuencia de funcionamiento del servicio de bayoneta

Antes de comenzar a desarrollar el verificador para el servicio de bayoneta, clasifiquemos la secuencia de ejecución de todo el servicio de bayoneta:

5.png

Entre ellos, las principales tareas de desarrollo del servicio de bayoneta: pasos 2, 3, 4 y 7.

4.2 Crear interfaz de tareas

Mencionamos anteriormente que la inspección de patrulla es un método de detección posterior, por lo que la capacidad principal de DataProviderBase (clase base de proveedor de datos) del sistema de inspección de patrulla es: "Sondeo periódico para recibir la lista de páginas para inspeccionar proporcionada externamente".

Para el servicio de bayoneta, la parte de detección crea activamente la tarea de detección, por lo que no es necesario que prestemos mucha atención a la implementación de DataProviderBase, sino que inicie un servicio de API que se encargue de crear la tarea de detección. es como sigue:

app.post('/xxx.xxx', async (req, res) => {
  const urls = req.body?.urls // 待检测url列表
  const callBack = req.body?.callBack // 调用方接收报告的回调接口地址
  const transData = req.body?.transData // 调用方需要在回调中拿到的透传数据
  // 巡检系统检测任务创建函数
  newApp.createJob(urls.map(url => ({ url,
      // 在redis任务队列中传递的信息
      pos: { callBack, transData },
    })),
    jobId => { // 返回任务id给调用方
      res.json({ taskId: jobId })
    }
  )
})



4.3 Detección de página

PageInspectorBase (la clase base del inspector de páginas) es el foco de la transformación del servicio de bayoneta. En términos de implementación de subclases de esta clase base, necesitamos hacer los casos de detección específicos mencionados anteriormente para implementarlos. Hay principalmente dos tipos de casos de detección:

1. Caso de detección de tipo de recurso de solicitud: anule el método onResponse en la subclase y ejecute una lógica de detección diferente para diferentes tipos de recursos;

2. Caso de detección en tiempo de ejecución: invalide el método onPageOpen en la subclase, inyecte el script js a través del objeto Page que se pasa desde la clase base y realice la detección en tiempo de ejecución de la página;

// 
页面检测类
class PageInspector extends PageInspectorBase {
  // ...
  // 针对不同资源类型检测方法配置Map
  checkResponseMethodsMap = new Map([['image', this.checkImageResponse]])
  
  // 请求资源型检测入口 针对请求资源进行检测
  async onResponse(response: Response, reporter: PageReporter, data: IJobItem) {
    const resourceType = response.request().resourceType()
    const checkMethod = this.checkResponseMethodsMap.get(resourceType)
    await checkMethod(response, reporter, data)
  }
  
  // 检测图片资源
  async checkImageResponse(response: Response, reporter: PageReporter, data: IJobItem) {
    // ...
    if (imageCdnList.includes(url)) {reporter.add({ errorType: "图片类型错误.非cdn资源" })}
    // ...
  }
    
  // 运行时检测入口 在页面打开时执行注入的js脚本进行运行时检测
  async onPageOpen(page, reporter: PageReporter, data) {
    // ...
    const htmlText = await page.evaluate('window.document.documentElement.innerHTML')
    const phoneRegex = /\b((?:\+?86)?1(?:3\d{3}|5[^4\D]\d{2}|8\d{3}|7(?:[35678]\d{2}|4(?:0\d|1[0-2]|9\d))|9[189]\d{2}|66\d{2})\d{6})\b/g;
    let phoneMatch: RegExpExecArray
    let collectMessage = []
    while ((phoneMatch = phoneRegex.exec(html)) !== null) {
      const phone = phoneMatch[1];collectMessage.push(`手机号码:${phone}`);
    }
    collectMessage.forEach(val => {reporter.add({ errorMessage: `敏感信息:${val}`})})
    // ...
  }
  // ...
}


RegExp.prototipo.exec()

Los objetos JavaScript RegExp tienen estado cuando se establece el indicador global o fijo (por ejemplo, /foo/g o /foo/y). Registran la posición desde la última coincidencia exitosa en la propiedad lastIndex. Con esta función, exec() se puede usar para iterar sobre varias coincidencias en una sola cadena (incluidas las coincidencias capturadas); en cambio, String.prototype.match() solo devolverá el resultado coincidente.

4.4 Informe y devolución de llamada

Después de ejecutar la tarea de detección, se creará una nueva "tarea de generación de informes" en reporter_queue, y el programa principal llama a la subclase que hereda DataReporterBase para realizar las siguientes operaciones:

  1. Ordene los elementos detectados uno por uno, clasifique los errores recopilados y ordene los datos de origen del informe;

  2. De acuerdo con los datos de origen del informe combinados con la plantilla ejs para generar html estático y cargarlo para obtener la dirección del informe de detección en línea;

  3. Informe de instrumentación de devolución de llamada a la persona que llama.

4.4.1 Generar una plantilla de informe usando ChatGPT

El nivel de diseño de la interfaz de usuario de la mayor parte de la investigación y el desarrollo es obvio para todos. En lugar de aplastar el estilo y la interacción de la plantilla de informe, es mejor dejarlo en manos de la IA. Ingrese la estructura de datos y los requisitos predefinidos, ChatGPT puede rápidamente proporcione una plantilla, y luego solo necesita un poco. Un poco de ajuste lo llevará a un estado utilizable.

Q: 我需要你写一个ejs模板,这个模板用来展示一个统计报告,为了样式和交互方便,模板会通过内置bootstrap的css样式和Jquery,你可以用到他们来实现html元素的组合和设置交互,具体的数据结构如下:

interface CheckResult {
  name: string;
  status: 0 | 1;
  message: string;
  severityLevel: 0 | 1;
}

interface DetectionResult {
  url: string;
  status: 0 | 1;
  checkResults: CheckResult[];
}

interface InspectorReport {
  taskId: string;
  reporterUrl?: string;
  detectionResults: DetectionResult[];
  startTimeStr: string;
  endTimeStr: string;
  duration: number;
  pageTotal: number;
  taskStat: {
    completed: number,
    waiting: number,
    active: number,
    delayed: number,
    paused: number,
    failed: number,
  }
}

export interface InspectorReportBase {
  manifest: IManifest,
  data: InspectorReport;
}

export interface IManifest {
  name: string
  desc?: string
  notifyTo?: string[]
}


A: 好的,以下是基于提供的数据结构设计的ejs模板:
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <link href="https://xxx.xxx.css" rel="stylesheet">
  <script src="https://xxx.xxx.js"></script>
  <title>
    <%=data.manifest.desc%>
  </title>
</head>

<body>
  <div class="container">
    <h2 class="text-center">
      <%= data.manifest.desc %> 统计报告
    </h2>

    <div class="row">
      <div class="col-md-4">
        <div class="card">
          <div class="card-body">
            <h5 class="card-title">任务信息</h5>
            <p class="card-text">任务ID: <%= data.data.taskId %>
            </p>
            <p class="card-text">检测开始时间: <%= data.data.startTimeStr %>
            </p>
            <p class="card-text">检测结束时间: <%= data.data.endTimeStr %>
            </p>
            <p class="card-text">检测时长: <%= data.data.duration %> 秒</p>
            <p class="card-text">检测页面数: <%= data.data.pageTotal %>
            </p>
            <!--以下省略 -->
</body>
</html>


Plantilla de informe en línea generada por IA:

6.png

4.4.2 Desacoplamiento de la persona que llama

Como proveedor de servicios, el servicio de bayoneta no quiere prestar demasiada atención a quién es la persona que llama, entonces, ¿cómo lograr el desacoplamiento de la persona que llama?

——Mirando hacia atrás en el enlace "Crear interfaz de tareas" anterior, los parámetros de entrada de este diseño de interfaz incluyen campos de devolución de llamada y transData:

  1. callBack: cuando finaliza la tarea de detección, el servicio de bayoneta llamará a esta dirección para devolver el informe de detección;

  2. transData: cuando finaliza la tarea de detección, los datos que deben pasarse de forma transparente a CallBack;

Una vez completada la tarea de detección de página, en el enlace del informe de prueba de devolución de llamada, el servicio de bayoneta obtendrá estos dos valores del caché de la tarea de la cola redis y utilizará la solicitud POST para enviar el informe y transData a la devolución de llamada.

卡口服务回调示例代码
axios.post(callBack, { 
  data: { msg: "本次检测检测报告如下:xxxxx", transData: `透传的数据如下:${transData}` }
})


En la planificación de seguimiento, para que el servicio de bayoneta se adapte a las diferentes necesidades de más escenarios, en referencia al concepto del centro de registro de microservicios de back-end, se puede realizar un modelo abstracto simple del centro de registro para desacopla aún más el servicio de bayoneta y su llamador. La lógica entre ellos puede expandir más funciones al mismo tiempo: elementos de detección personalizados, plantillas de informes personalizados, etc.

7.jpeg

5 resumen

Para el servicio de bayoneta, aprender y leer el código fuente de inspección es un trabajo previo importante. Al comprender en profundidad los detalles de implementación y el diseño de la arquitectura subyacente del sistema de inspección, puede comprender mejor cómo funciona el sistema de inspección, a fin de personalizarlo y expandirlo mejor. Estas experiencias también han ayudado a mejorar sus capacidades de diseño y codificación. aplicarse y practicarse en proyectos técnicos posteriores. Espero que los estudiantes de desarrollo que han leído este artículo puedan aprender algo de este resumen práctico~

Enlace de cita/referencia

GitHub - OptimalBits/toro

RegExp.prototype.exec() - JavaScript | MDN

Texto: Hang Fei

Este artículo pertenece al original de la tecnología Dewu, fuente: sitio web oficial de la tecnología Dewu

¡Está estrictamente prohibido reimprimir sin el permiso de Dewu Technology, de lo contrario, se investigará la responsabilidad legal de acuerdo con la ley!

{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/5783135/blog/10084228
Recomendado
Clasificación