Как настроить секционирование в Athena для журналов балансировки нагрузки приложений

#amazon-web-services #amazon-s3 #aws-lambda #amazon-athena #partition

#amazon-web-services #amazon-s3 #aws-lambda #amazon-athena #раздел

Вопрос:

У нас есть журналы балансировки нагрузки приложений в s3, которые мы запрашиваем с помощью Athena. Мы хотели бы добавить разделы для года, месяца, даты.

Я следую официальной документации AWS, которая перенаправляет на страницу github для добавления разделов в таблицу.

Я следовал руководству, но когда я когда-либо создаю таблицу с разделами, либо записи не возвращаются, либо они пусты.

 CREATE EXTERNAL TABLE IF NOT EXISTS alb_logs (  
  type string,  
  time string,  
  elb string,  
  client_ip string,  
  client_port int,  
  target_ip string,  
  target_port int,  
  request_processing_time double,  
  target_processing_time double,  
  response_processing_time double,  
  elb_status_code string,  
  target_status_code string,  
  received_bytes bigint,  
  sent_bytes bigint,  
  request_verb string,  
  request_url string,  
  request_proto string,
  user_agent string,  
  ssl_cipher string,  
  ssl_protocol string,  
  target_group_arn string,  
  trace_id string,  
  domain_name string,  
  chosen_cert_arn string,
  matched_rule_priority string,  
  request_creation_time string,
  actions_executed string,
  redirect_url string,
  error_reason string
)
PARTITIONED BY(year string, month string, day string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
'serialization.format' = '1',
'input.regex' =
'([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) "([^ ]*) ([^ ]*) (- |[^ ]*)" "([^"]*)" ([A-Z0-9-] ) ([A-Za-z0-9.-]*) ([^ ]*) "([^"]*)" "([^"]*)" "([^"]*)" ([-.0-9]*) ([^ ]*) "([^"]*)" "([^ ]*)" "([^ ]*)"' )
LOCATION 's3://{LOG_BUCKET}/AWSLogs/{AWS_account_ID}/elasticloadbalancing/us-east-1/';
 

(мы не используем префикс в наших журналах)

Если я удалю PARTITIONED BY(year string, month string, day string) часть, то у меня будет создана соответствующая таблица без разделов, из которой я могу запрашивать данные.

Когда я добавляю часть раздела, я получаю 0 записей. Читая дальше, насколько я понимаю, мне нужно добавить эти разделы. С этой страницы github

Этот шаблон создает лямбда-функцию для добавления раздела и запланированного события CloudWatch. Журналы отправляются из балансировщика нагрузки в корзину S3. Ежедневно запланированное событие CloudWatch вызывает функцию Lambda для добавления раздела в таблицу Athena.

Но, честно говоря, я не совсем понимаю эту часть. Однако я пошел дальше и развернул предоставленный шаблон CloudFormation с соответствующими параметрами. Однако теперь я получаю возвращаемые записи для простого запроса select all

 select * from alb_logs where year = '2020' and month "12" limit 100 
 

все поля пусты, кроме ключей раздела year , month и day (они не были без partition участия в create table command, что для меня указывает на то, что регулярное выражение не является проблемой)

Любая помощь в понимании того, что я делаю неправильно, и как правильно это настроить, будет высоко оценена.

Ответ №1:

Это не имеет никакого отношения к разделам. Вероятно, это проблема с характером персонажа. Возможно, новая строка в конце вашего ввода. регулярное выражение в определении таблицы или что-то в этом роде. Проверьте мой рабочий пример в файле cloudformation yml для таблицы, настроенной для ведения журнала балансировщика нагрузки:

 AlbAthenaTable:
    Type: AWS::Glue::Table
    Properties:
      CatalogId: !Ref AWS::AccountId
      DatabaseName: !Ref AthenaDataBase
      TableInput:
        Name: 
          !Join 
            - '_'
            - !Split 
                - '-'
                - !Sub ${AWS::StackName}_alb_table
        TableType: EXTERNAL_TABLE
        Parameters: { 
          "projection.day.type": "integer",
          "projection.day.range": "1,31",
          "projection.enabled": "true" }
        PartitionKeys:
        - Name: day
          Type: int
        StorageDescriptor:
          OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
          Columns:
            - Name: type
              Type: string
            - Name: time
              Type: string
            - Name: elb
              Type: string
            - Name: client_ip
              Type: string
            - Name: client_port
              Type: int
            - Name: target_ip
              Type: string
            - Name: target_port
              Type: int
            - Name: request_processing_time
              Type: double
            - Name: target_processing_time
              Type: double
            - Name: response_processing_time
              Type: double
            - Name: elb_status_code
              Type: string
            - Name: target_status_code
              Type: string
            - Name: received_bytes
              Type: bigint
            - Name: sent_bytes
              Type: bigint
            - Name: request_verb
              Type: string
            - Name: request_url
              Type: string
            - Name: request_proto
              Type: string
            - Name: user_agent
              Type: string
            - Name: ssl_cipher
              Type: string
            - Name: ssl_protocol
              Type: string 
            - Name: target_group_arn
              Type: string 
            - Name: trace_id 
              Type: string 
            - Name: domain_name
              Type: string 
            - Name: chosen_cert_arn 
              Type: string 
            - Name: matched_rule_priority
              Type: string
            - Name: request_creation_time 
              Type: string
            - Name: actions_executed  
              Type: string
            - Name: redirect_url  
              Type: string
            - Name: lambda_error_reason
              Type: string
            - Name: target_port_list
              Type: string
            - Name: target_status_code_list
              Type: string
            - Name: classification
              Type: string
            - Name: classification_reason
              Type: string
          InputFormat: org.apache.hadoop.mapred.TextInputFormat
          Location: 
            !Sub s3://${LoggingBucket}/${Prefix}/
          SerdeInfo:
            Parameters:
                serialization.format: 1
                input.regex: >-
                  ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) "([^ ]*) ([^ ]*) (- |[^ ]*)" "([^"]*)" ([A-Z0-9-] ) ([A-Za-z0-9.-]*) ([^ ]*) "([^"]*)" "([^"]*)" "([^"]*)" ([-.0-9]*) ([^ ]*) "([^"]*)" "([^"]*)" "([^ ]*)" "([^s] ?)" "([^s] )" "([^ ]*)" "([^ ]*)"
            SerializationLibrary: org.apache.hadoop.hive.serde2.RegexSerDe
 

вам нужно перейти в консоль каталога данных aws glue и проверить ваше регулярное выражение input.regex в SerderInfo в свойствах таблицы и убедиться, что оно выглядит следующим образом:

 "input.regex": "([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) "([^ ]*) ([^ ]*) (- |[^ ]*)" "([^"]*)" ([A-Z0-9-] ) ([A-Za-z0-9.-]*) ([^ ]*) "([^"]*)" "([^"]*)" "([^"]*)" ([-.0-9]*) ([^ ]*) "([^"]*)" "([^"]*)" "([^ ]*)" "([^s] ?)" "([^s] )" "([^ ]*)" "([^ ]*)""
 

вместо:

 "input.regex": "([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) "([^ ]*) ([^ ]*) (- |[^ ]*)" "([^"]*)" ([A-Z0-9-] ) ([A-Za-z0-9.-]*) ([^ ]*) "([^"]*)" "([^"]*)" "([^"]*)" ([-.0-9]*) ([^ ]*) "([^"]*)" "([^"]*)" "([^ ]*)" "([^s] ?)" "([^s] )" "([^ ]*)" "([^ ]*)"n"
 

здесь важно отметить, что у вас не может быть новой строки (ни пробелов, ни других символов) в конце вашего ввода.регулярное выражение! Если это так, вы получите сообщение об ошибке, о котором сообщили.

Я рекомендую вам создать таблицу, аналогичную примеру документации. после этого создайте свой и, если у вас возникнут какие-либо проблемы, проверьте, нет ли различий между их настройками.

Пример документации:

https://docs.aws.amazon.com/athena/latest/ug/application-load-balancer-logs.html

Еще одна вещь (немного не по теме, но очень полезная для ваших целей) заключается в том, что вы можете использовать функцию, называемую partitions-projection, для прогнозирования разделов на уровне определения таблицы. Если вы используете эту функцию, вам вообще не нужно вручную добавлять новые разделы или использовать для этого планировщик с лямбдой.

Проверьте документы:

https://docs.aws.amazon.com/athena/latest/ug/partition-projection.html#partition-projection-using

Я также использую эту функцию в своем шаблоне, в этой части:

 ...
 TableInput:
        ...
        Parameters: { 
          "projection.day.type": "integer",
          "projection.day.range": "1,31",
          "projection.enabled": "true" }
        PartitionKeys:
        - Name: day
          Type: int
        ....
 

в моем случае я просто использую целое число. Но прогнозирование разделов поддерживает тип даты и другие типы.

Еще один совет не по теме:

Я знаю, что разделение и весь этот процесс могут быть немного сложными, поэтому вот статья, в которой весь этот процесс объясняется очень глубоко и очень понятно (речь идет о cloudfront, но основы те же):

https://aws.amazon.com/blogs/big-data/analyze-your-amazon-cloudfront-access-logs-at-scale/

Вот репозиторий github, связанный со статьей выше, он очень полезен:

https://github.com/aws-samples/amazon-cloudfront-access-logs-queries