写点什么

使用 Fluent Bit 实现集中式容器日志记录

  • 2019-09-24
  • 本文字数:16197 字

    阅读完需:约 53 分钟

使用 Fluent Bit 实现集中式容器日志记录

AWS 专为构建师打造。构建师一直致力于寻找优化方法,而应用程序日志记录也是如此。并非所有日志都同等重要。一些日志需要实时分析,而一些日志只需长期存储,以便在需要时进行分析。因此,能够轻松地将日志路由到 AWS 及其合作伙伴提供的各种存储和分析工具非常重要。


正因如此,我们支持在 Fluent Bit 的帮助下创建简单的扩展点,以便将日志从容器化应用程序流式传输到 AWS 和合作伙伴解决方案,从而保留日志并进行分析。新推出的 AWS Fluent Bit 插件以容器映像的形式提供,利用该插件,您可以将日志路由到 Amazon CloudWatch Amazon Kinesis Data Firehose 目标位置(其中包括 Amazon S3、Amazon Elasticsearch ServiceAmazon Redshift)。在本博文中,我们将展示如何在 Amazon ECS 和 EKS 集群上实际运用 Fluent Bit 插件。如果您不熟悉工具,可能还要查看有关 Fluentd 和 Kinesis Firehose 基础知识的教程,并了解 AWS 容器路线图中的相关问题,尤其是 #10#66

日志路由简介

从概念上讲,容器化设置(如 Amazon ECS 或 EKS)中的日志路由如下图所示:



在上图左侧,描述了日志源(从底部开始):


  1. 主机和控制层面级别由 EC2 实例组成,用于托管容器。您可以直接(或不直接)访问这些实例。例如,对于在 Fargate 上运行的容器,您将不会在 EC2 控制台中看到实例。在此级别,您还将获得 AWS 管理的 EKS 控制层面中的日志。

  2. 容器运行时级别通常包括 Docker 引擎生成的日志,例如 ECS 中的代理日志。这些日志通常对具有基础设施管理角色的人员最有用,但也可以帮助开发人员排查问题。

  3. 应用程序级别用于运行用户代码。此级别会生成与特定应用程序有关的日志,例如有关您自己应用程序中的操作结果的日志条目,或现成应用程序组件(如 NGINX)的应用程序日志。


接下来是路由组件:即 Fluent Bit。该组件负责从所有源读取日志,并将日志记录路由到各个目标位置(也称为日志接收器)。此路由组件需要以某种形式运行,例如作为 Kubernetes pod/ECS 任务中的伴生服务,或者作为主机级守护程序集。


下游日志接收器将日志用于不同的目的并供不同的受众使用。其中包括大量使用案例,从日志分析到确保合规性(日志需要在指定的保留期内存储),当人类用户需要收到事件通知时发出提醒;控制面板日志提供(实时)图表集合,帮助人类用户快速了解系统的整体状态。


了解这些基础知识后,下面我们看一个具体的使用案例:使用 Fluent Bit 实现多集群应用程序的集中式日志记录。Amazon ECS Fluent Bit 守护程序服务 GitHub 存储库中提供了所有容器定义和配置。

集中式日志记录的实际应用:多集群日志分析

为了展示 Fluent Bit 在实际中的应用,我们将跨 Amazon ECS 和 Amazon EKS 集群执行多集群日志分析,并将 Fluent Bit 部署和配置为守护程序集。运行在每个集群中的 NGINX 应用程序生成的应用程序级日志由 Fluent Bit 捕获,并通过 Amazon Kinesis Data Firehose 流式传输到 Amazon S3,然后我们可以在这里使用 Amazon Athena 进行查询:


Amazon ECS 设置

在 EC2 集群上使用以下用户数据(在我们的示例中,在名为 enable-fluent-log-driver.sh 的文件中)创建 ECS,以便在 ECS 代理中启用 Fluentd 日志驱动程序:


#!/bin/bashecho "ECS_AVAILABLE_LOGGING_DRIVERS=[\"awslogs\",\"fluentd\"]" >> /etc/ecs/ecs.config
复制代码


注意:此步骤假设您已安装 ECS CLI


例如,我们在 EC2 集群上创建以下 ECS:


$ ecs-cli up \          --size 2 \          --instance-type t2.medium \          --extra-user-data enable-fluent-log-driver.sh \          --keypair fluent-bit-demo-key \          --capability-iam \          --cluster-config fluent-bit-demo
复制代码


接下来,我们需要构建一个包含 Fluent Bit 配置的容器映像。为此,我们将创建一个包含以下内容的 Dockerfile


FROM amazon/aws-for-fluent-bit:1.2.0ADD fluent-bit.conf /fluent-bit/etc/ADD parsers.conf /fluent-bit/etc/
复制代码


注意:此次未遵循良好的安全实践,没有定义 USER,而是让其以 root 身份运行。这是有意而为,因为 Fluent Bit 当前需要以 root 身份运行。


上述 Dockerfile 又依赖两个配置文件:第一个是 fluent-bit.conf


[SERVICE]    Parsers_File parsers.conf
[INPUT] Name forward unix_path /var/run/fluent.sock
[FILTER] Name parser Match ** Parser nginx Key_Name log
[OUTPUT] Name firehose Match ** delivery_stream my-stream region some-region
复制代码


其次是 parsers.conf,用于解析 NGINX 日志:


[PARSER]    Name   nginx    Format regex    Regex ^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")? \"-\"$ Time_Key time Time_Format %d/%b/%Y:%H:%M:%S %z
复制代码


现在,我们将构建自定义容器映像,并将其推送到一个名为 fluent-bit-demo 的 ECR 存储库:


# build the custom image$ docker build --tag fluent-bit-demo:0.1 .# push to Amazon ECR:$ ecs-cli push fluent-bit-demo:0.1
复制代码


访问 ECR 控制台,确认映像构建和推送是否成功;您应会看到与下面类似的内容:



现在,我们可以使用上述容器映像启动包含守护程序计划策略的 ECS 服务,以将自定义配置的 Fluent Bit 部署到集群中:


$ aws cloudformation deploy \      --template-file ecs-fluent-bit-daemonset.yml \      --stack-name ecs-fluent-bit-daemon-service \      --parameter-overrides \      EnvironmentName=fluentbit-daemon-service \      DockerImage=XXXXXXXXXXXX.dkr.ecr.us-west-2.amazonaws.com/fluent-bit-demo:0.1 \      Cluster=fluent-bit-demo \      --region $(aws configure get region) \      --capabilities CAPABILITY_NAMED_IAM
复制代码


在 ECS 控制台中,您现在应会看到与下面类似的内容:



现在,我们可以基于以下任务定义,启动 ECS 服务,即运行 NGINX:


{    "taskDefinition": {        "taskDefinitionArn": "arn:aws:ecs:us-west-2:XXXXXXXXXXXX:task-definition/nginx:1",        "containerDefinitions": [            {                "name": "nginx",                "image": "nginx:1.17",                "memory": 100,                "essential": true,                "portMappings": [                    {                        "hostPort": 80,                        "protocol": "tcp",                        "containerPort": 80                    }                ],                "logConfiguration": {                    "logDriver": "fluentd",                    "options": {                        "fluentd-address": "unix:///var/run/fluent.sock",                        "tag": "logs-from-nginx"                    }                }            }        ],        "family": "nginx"    }}
复制代码


创建上述任务定义之后,现在应该会在 ECS 控制台中看到以下内容:



现在,我们可以基于上述任务定义启动 ECS 服务:


$ aws ecs create-service \      --cluster fluent-bit-demo \      --service-name nginx-svc \      --task-definition nginx:1 \      --desired-count 1
复制代码


如果一切顺利,您应该会在 ECS 控制台中看到与下面类似的内容:



至此,我们已设置好 ECS 部分。现在,我们在 Amazon EKS 上运行的 Kubernetes 集群中配置相同的设置。

Amazon EKS 设置

使用 eksctl 创建一个名为 fluent-bit-demo的 Amazon EKS 集群,如 EKS 文档中所示,然后创建一个名为 eks-fluent-bit-daemonset-policy.json 的策略文件(来源),其中包含以下内容:


{    "Version": "2012-10-17",    "Statement": [        {            "Effect": "Allow",            "Action": [                "firehose:PutRecordBatch"            ],            "Resource": "*"        },        {            "Effect": "Allow",            "Action": "logs:PutLogEvents",            "Resource": "arn:aws:logs:*:*:log-group:*:*:*"        },        {            "Effect": "Allow",            "Action": [                "logs:CreateLogStream",                "logs:DescribeLogStreams",                "logs:PutLogEvents"            ],            "Resource": "arn:aws:logs:*:*:log-group:*"        },        {            "Effect": "Allow",            "Action": "logs:CreateLogGroup",            "Resource": "*"        }    ]}
复制代码


要将此策略文件附加到 EC2 工作线程节点上的 EKS,请按以下顺序执行操作:


$ STACK_NAME=$(eksctl get nodegroup --cluster fluent-bit-demo -o json | jq -r '.[].StackName')
$ INSTANCE_PROFILE_ARN=$(aws cloudformation describe-stacks --stack-name $STACK_NAME | jq -r '.Stacks[].Outputs[] | select(.OutputKey=="InstanceProfileARN") | .OutputValue')
$ ROLE_NAME=$(aws cloudformation describe-stacks --stack-name $STACK_NAME | jq -r '.Stacks[].Outputs[] | select(.OutputKey=="InstanceRoleARN") | .OutputValue' | cut -f2 -d/)
$ aws iam put-role-policy \ --role-name $ROLE_NAME \ --policy-name FluentBit-DS \ --policy-document file://eks-fluent-bit-ds-policy.json
复制代码


现在我们继续定义 Kubernetes RBAC 设置,即 Fluent Bit pod 将使用的服务账户以及角色和角色绑定。


首先创建服务账户 fluent-bit(稍后我们将在守护程序集中使用):


$ kubectl create sa fluent-bit
复制代码


接下来,在名为 eks-fluent-bit-daemonset-rbac.yaml 的文件(来源)中定义角色和绑定:


apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRolemetadata:  name: pod-log-readerrules:- apiGroups: [""]  resources:  - namespaces  - pods  verbs: ["get", "list", "watch"]---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata:  name: pod-log-crbroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: pod-log-readersubjects:- kind: ServiceAccount  name: fluent-bit  namespace: default
复制代码


现在,通过执行 kubectl apply -f eks-fluent-bit-ds-rbac.yaml,创建上面定义的角色和角色绑定。


接下来,在名为 eks-fluent-bit-configmap.yaml 的文件(来源)中通过 Kubernetes 配置映射定义 Fluent Bit 配置:


apiVersion: v1kind: ConfigMapmetadata:  name: fluent-bit-config  labels:    app.kubernetes.io/name: fluentbitdata:  fluent-bit.conf: |    [SERVICE]        Parsers_File  parsers.conf    [INPUT]        Name              tail        Tag               kube.*        Path              /var/log/containers/*.log        Parser            docker        DB                /var/log/flb_kube.db        Mem_Buf_Limit     5MB        Skip_Long_Lines   On        Refresh_Interval  10    [FILTER]        Name parser        Match **        Parser nginx        Key_Name log    [OUTPUT]        Name firehose        Match **        delivery_stream eks-stream        region us-west-2   parsers.conf: |    [PARSER]        Name   nginx        Format regex        Regex ^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")? \"-\"$ Time_Key time Time_Format %d/%b/%Y:%H:%M:%S %z
复制代码


通过执行 kubectl apply -f eks-fluent-bit-confimap.yaml 应用此配置映射,然后在名为 eks-fluent-bit-daemonset.yaml 的文件(来源)中定义 Kubernetes 守护程序集(使用提到的配置映射):


apiVersion: apps/v1kind: DaemonSetmetadata:  name: fluentbit  labels:    app.kubernetes.io/name: fluentbitspec:  selector:    matchLabels:      name: fluentbit  template:    metadata:      labels:        name: fluentbit    spec:      serviceAccountName: fluent-bit      containers:      - name: aws-for-fluent-bit        image: amazon/aws-for-fluent-bit:1.2.0        volumeMounts:        - name: varlog          mountPath: /var/log        - name: varlibdockercontainers          mountPath: /var/lib/docker/containers          readOnly: true        - name: fluent-bit-config          mountPath: /fluent-bit/etc/        - name: mnt          mountPath: /mnt          readOnly: true        resources:          limits:            memory: 500Mi          requests:            cpu: 500m            memory: 100Mi      volumes:      - name: varlog        hostPath:          path: /var/log      - name: varlibdockercontainers        hostPath:          path: /var/lib/docker/containers      - name: fluent-bit-config        configMap:          name: fluent-bit-config      - name: mnt        hostPath:          path: /mnt
复制代码


最后,通过执行以下命令启动 Fluent Bit 守护程序集:


$ kubectl apply -f eks-fluent-bit-daemonset.yaml
复制代码


通过查看日志,验证 Fluent Bit 守护程序集:


$ kubectl logs ds/fluentbitFound 3 pods, using pod/fluentbit-9zszmFluent Bit v1.1.3Copyright (C) Treasure Data
[2019/07/08 13:44:54] [ info] [storage] initializing...[2019/07/08 13:44:54] [ info] [storage] in-memory[2019/07/08 13:44:54] [ info] [storage] normal synchronization mode, checksum disabled[2019/07/08 13:44:54] [ info] [engine] started (pid=1)[2019/07/08 13:44:54] [ info] [in_fw] listening on unix:///var/run/fluent.sock...[2019/07/08 13:44:55] [ info] [sp] stream processor started
复制代码


接下来,通过 kubectl apply -f eks-nginx-app.yaml 部署以下 NGINX 应用程序


apiVersion: apps/v1kind: Deploymentmetadata:  name: nginx  labels:    app.kubernetes.io/name: nginxspec:  replicas: 4   selector:    matchLabels:      app: nginx  template:    metadata:      labels:        app: nginx    spec:      containers:      - name: nginx        image: nginx:1.17        ports:        - containerPort: 80---apiVersion: v1kind: Servicemetadata:  name: nginx  labels:    app: nginxspec:  ports:  - port: 80    targetPort: 80  selector:    app: nginx
复制代码


至此,我们已完成日志源和路由设置。现在,我们将使用从在 ECS 和 EKS 中运行的 NGINX 容器收集的所有日志数据执行实际任务:我们将对日志进行集中分析。

跨集群执行日志分析

目标是对在 ECS 和 EKS 集群中运行的 NGINX 容器进行日志分析。为此,我们使用 Amazon Athena,这样可以使用 SQL 以交互方式从 Amazon S3 查询服务日志数据。但是,在查询 S3 中的数据之前,我们需要从中获得日志数据。


请注意,在上述 ECS 和 EKS 的 Fluent Bit 配置中,我们将输出设置为 delivery_stream xxx-stream。 这是 Amazon Kinesis Firehose 传输流,我们需要先为 ECS 和 EKS 创建传输流。


首先,通过定义允许 Firehose 写入 S3 的有效策略来设置访问控制部分。为此,我们需要使用两个策略文件创建一个新的 IAM 角色。第一个是 firehose-policy.json来源):


{  "Version": "2012-10-17",  "Statement": {      "Effect": "Allow",      "Principal": {        "Service": "firehose.amazonaws.com"      },      "Action": "sts:AssumeRole"  }}
复制代码


第二个是 firehose-delivery-policy.json 策略文件(来源),在该文件中,将 XXXXXXXXXXXX 替换为您自己的账户 ID(如果您不确定 ID 是什么,可以通过执行 aws sts get-caller-identity --output text --query 'Account' 获取)。同样,在 S3 部分,将 mh9-firelens-demo 替换为您自己的存储桶名称。


现在,我们可以创建 firehose_delivery_role,以用于 ECS 和 EKS 传输流:


$ aws iam create-role \        --role-name firehose_delivery_role \        --assume-role-policy-document file://firehose-policy.json
复制代码


记下上述命令 JSON 输出结果中的角色 ARN,其格式为 arn:aws:iam::XXXXXXXXXXXXX:role/firehose_delivery_role。我们稍后在创建传输流时会用到,但在创建传输流之前,我们必须实施在 firehos- delivery-policy.json 中定义的策略:


$ aws iam put-role-policy \        --role-name firehose_delivery_role \        --policy-name firehose-fluentbit-s3-streaming \        --policy-document file://firehose-delivery-policy.json
复制代码


现在,创建 ECS 传输流:


$ aws firehose create-delivery-stream \            --delivery-stream-name ecs-stream \            --delivery-stream-type DirectPut \            --s3-destination-configuration \RoleARN=arn:aws:iam::XXXXXXXXXXXX:role/example_firehose_delivery_role,\BucketARN="arn:aws:s3:::mh9-firelens-demo",\Prefix=ecs
复制代码


注意:以上命令中的空格很重要:RoleARN 等必须位于一行中且不含空格。


现在,我们必须对 EKS 传输流重复以上操作,重用在第一步中创建的角色。(换句话说,您只需重复执行 aws firehose create-delivery-stream 命令,将 ecs-stream 替换为 eks-stream,将 Prefix=ecs 替换为 Prefix=eks 即可。)


创建并激活传输流需要几分钟时间。当您看到与下面类似的内容时,表示您可以进行下一步:



现在,我们需要为在 ECS 和 EKS 中运行的 NGINX 容器生成一些负载。您可以获取 ECSEKS 的负载生成器文件并执行以下命令;这将每两秒对相应的 NGINX 服务执行一次 curl 操作(在后台执行),直到您终止脚本。


$ ./load-gen-ecs.sh &$ ./load-gen-eks.sh &
复制代码


现在我们有了来自 NGINX Web 服务器的一些日志数据,便可以通过 Athena 查询 S3 中的日志条目。为此,我们必须首先为 ECS 和 EKS 创建表,告知 Athena 我们正在使用的架构(下面显示了 ECS 日志数据的架构,对于 EKS,也是如此):


CREATE EXTERNAL TABLE fluentbit_ecs (    agent string,    code string,    host string,    method string,    path string,    referer string,    remote string,    size string,    user string)ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'LOCATION 's3://mh9-firelens-demo/ecs2019/'
复制代码


注意:Amazon Athena 不导入或提取数据;它直接在 S3 中查询数据。因此,当日志数据通过 Fluent Bit 和 Firehose 传输流从 NGINX 容器到达 S3 存储桶中时,您可以使用 Athena 进行查询。


接下来,使用以下 SQL 语句,创建 ECS 和 EKS 日志条目的整合视图


CREATE OR REPLACE VIEW "fluentbit_consolidated" ASSELECT * , 'ECS' as sourceFROM fluentbit_ecsUNIONSELECT * , 'EKS' as sourceFROM fluentbit_eks
复制代码


这样,我们可以合并这两个表(使用相同的架构),再添加一个源以标记源 ECS 或 EKS。现在,我们可以执行 SQL 查询,找出两个集群中使用 NGINX 服务的前 10 位用户


SELECT source,         remote AS IP,         count(remote) AS num_requestsFROM fluentbit_consolidatedGROUP BY  remote, sourceORDER BY  num_requests DESC LIMIT 10
复制代码


这将生成与下面类似的结果:



就这么简单! 您已经成功设置了 Fluent Bit 插件,并在两个不同的托管 AWS 容器环境(ECS 和 EKS)中使用它来执行日志分析。


完成之后,不要忘记删除相应的工作负载,包括 Kubernetes NGINX 服务(它进而会删除负载均衡器),并销毁 EKS 和 ECS 集群(这会销毁其中的容器)。最后但同样重要的一点是,清理包含日志数据的 Kinesis 传输流和 S3 存储桶。


为了未来使用更加便利,我们还在开发一项进一步简化在 AWS Fargate、Amazon ECS 和 Amazon EKS 上安装和配置 Fluent Bit 插件的功能。您可以通过 AWS 容器路线图的问题 10 关注该功能。

性能和后续步骤说明

为了更好地了解性能,我们执行了基准测试,将上面的 Fluent Bit 插件与 Fluentd CloudWatchKinesis Firehose 插件进行了比较。我们所有的测试都是在 c5.9xlarge EC2 实例上执行的。 结果如下:


CloudWatch 插件:Fluentd 与 Fluent Bit


每秒日志行数数据输出Fluentd CPUFluent Bit CPUFluentd 内存Fluent Bit 内存
10025KB/秒0.013 vCPU0.003 vCPU146MB27MB
1000250KB/秒0.103 vCPU0.03 vCPU303MB44MB
100002.5MB/秒1.03 vCPU0.19 vCPU376MB65MB


测试表明,Fluent Bit 插件比 Fluentd 更节省资源。平均而言,Fluentd 使用的 CPU 是 Fluent Bit 插件的 4 倍以上,所用内存是 Fluent Bit 插件的 6 倍以上。


Kinesis Firehose 插件:Fluentd 与 Fluent Bit


每秒日志行数数据输出Fluentd CPUFluent Bit CPUFluentd 内存Fluent Bit 内存
10025KB/秒0.006 vCPU0.003 vCPU84MB27MB
1000250KB/秒0.073 vCPU0.033 vCPU102MB37MB
100002.5MB/秒0.86 vCPU0.13 vCPU438MB55MB


在此基准测试中,平均而言,Fluentd 使用的 CPU 和内存分别是 Fluent Bit 插件的 3 倍和 4 倍以上。请注意,这些数据并未提供任何保证;您占用的资源可能有所不同。不过,上述数据点表明 Fluent Bit 插件的效率显著高于 Fluentd。

后续步骤

我们很高兴您能够在自己的集群上尝试此插件。如果某些操作未按预期运行,请告知我们,并且请分享您对性能/资源占用以及使用案例的见解。请就 GitHub 中的问题留言,或者在 GitHub 上提出有关 AWS 容器路线图的问题。

作者简介

Wesley Pettit,AWS 容器服务团队的软件开发人员。


本文转载自 AWS 技术博客。


原文链接:


https://amazonaws-china.com/cn/blogs/china/centralized-container-logging-fluent-bit/


2019-09-24 16:083061
用户头像

发布了 1855 篇内容, 共 121.9 次阅读, 收获喜欢 79 次。

关注

评论

发布
暂无评论
发现更多内容

Linux 网络管理技术 OSI 七层模型和 TCP/IP 四层模型

学神来啦

Linux 运维 IP

防火墙 Keepalived 异常双活恢复后部分外网访问中断问题分析

Qunar技术沙龙

运维 防火墙 网络 故障诊断 keep-alive

2021Java春招面试真题详解,Git-如何优雅地回退代码

策划Java工程师

Java 程序员 后端

2021最新Java面试真题解析!1

策划Java工程师

Java 程序员 后端

编译脚本:编写CMakeFile(一)

正向成长

CMakeFile

双非本化学跨专业,投岗阿里/滴滴后端三面,最终拿下offer

编程菌

Java 编程 程序员 面试 计算机

从河南暴雨、疫情反弹看区块链“灾疫”治理

CECBC

2021Java面经:Android屏幕适配-重点盘点

策划Java工程师

Java 程序员 后端

graphql计算指令之@filter:查询中实现集合过滤

杜艮魁

开源 后端 低代码 graphql

Hologres揭秘:深度解析高效率分布式查询引擎

阿里云大数据AI技术

【最不佳实践】Serverless应用优化四则

刘宇

Serverless 优化

2021年五面蚂蚁,从单体到分布式,必须解决的四个问题

策划Java工程师

Java 程序员 后端

2021金三银四,开发者进阿里必看的30道经典数据库面试题【附详细解析

策划Java工程师

Java 程序员 后端

2021BTAJ面试真题详解,16条代码规范建议,快看看自己做到没

Java 程序员 后端

下一个颠覆的领域:区块链如何影响审计行业?(下)

CECBC

2021Java笔试题总结!Java个人学习之旅(第十天)

策划Java工程师

Java 程序员 后端

2021程序员进阶宝典!《零基础(1)

策划Java工程师

Java 程序员 后端

3个月学会Java开发!Git-如何优雅地回退代码(1)

Java 程序员 后端

面试官:你了解JVM的锁优化吗?

百度开发者中心

Java 最佳实践 方法论 语言 & 开发

Python代码阅读(第2篇):数字转化成列表

Felix

Python 编程 Code Programing 阅读代码

2021Java大厂面试集合,java多线程

策划Java工程师

Java 程序员 后端

2021年Java开发实战!仿微信的网络聊天室项目开发【完整源码讲解

策划Java工程师

Java 程序员 后端

2021年Java知识体系总结,部门老大:redis-分布式锁再这么用

策划Java工程师

Java 程序员 后端

15个经典面试问题,酸!校招进字节跳动

Java 程序员 后端

5分钟搞定!从Java底层分析多线程行为

Java 程序员 后端

Selenium 4以后,再不相见的API

FunTester

自动化 API selenium

graphql计算指令之@sortBy:查询中实现列表字段排序

杜艮魁

开源 后端 低代码 graphql

关于Spring注解开发教程,打包全送你

华为云开发者联盟

Java spring 容器 注解 组件

区块链技术如何有效应对气候变化

CECBC

ironSource 在 2021 ChinaJoy 举办多场活动赋能中国开发者

80后程序员感慨中年危机,如何设计一个优雅的RESTFUL的接口

Java 程序员 后端

使用 Fluent Bit 实现集中式容器日志记录_容器_亚马逊云科技 (Amazon Web Services)_InfoQ精选文章