防丢失:大家去看原文

参考:https://www.cnblogs.com/rexcheny/articles/12884990.html

参考:https://www.orchome.com/553

参考:https://www.cnblogs.com/xiao987334176/p/10110389.html

https://www.imooc.com/article/269136?block_id=tuijian_wz

https://docs.vmware.com/en/VMware-Smart-Assurance/10.1.0/sa-ui-installation-config-guide-10.1.0/GUID-DF659094-60D3-4E1B-8D63-3DE3ED8B0EDF.html

https://www.it1352.com/1577965.html

参考:https://www.cnblogs.com/smartloli/p/12950761.html

https://www.jianshu.com/p/d54e0f0357ca

https://www.orchome.com/1959

https://www.orchome.com/171

Kafka的认证机制

概述
GSSAPI:使用的Kerberos认证,可以集成目录服务,比如AD。Kafka最小版本 0.9
PLAIN:使用简单用户名和密码形式,Kafka最小版本 0.10
SCRAM:主要解决PLAIN动态更新问题以及安全机制,Kafka最小版本 0.10.2
OAUTHBEARER:基于OAuth 2认证框架,Kafka最小版本 2.0
配置SASL\PLAIN
创建kafka_server_jaas.conf文件
这个文件是配置Broker服务端的JAAS,进入Kafka程序目录的config目录中,执行下面的命令:

touch kafka_server_jaas.confKafkaServer {org.apache.kafka.common.security.plain.PlainLoginModule required
username="admin"
password="admin"
user_admin="admin"
user_rex="123456"
user_alice="123456";
user_lucy="123456";
};
Client {org.apache.zookeeper.server.auth.DigestLoginModule required
username="admin"
password="admin";
};

上面的文件配置要顶格写。另外上面的username=“admin” password="admin"只是定义了broker间通信使用的用户名和密码,但是并不是创建用户的函数以,所以后面要写user_admin=“admin”,来创建创建用,如果你不创建,那么broker启动将会报验证失败的错误。

KafkaServer字段是用来配置broker间通信使用的用户名和密码以及客户端连接时需要的用户名和密码,其中username和password是broker用于初始化连接到其他的broker,kafka用户为broker间的通讯。在一个Kafka集群中,这个文件的内容要一样,集群中每个Borker去连接其他Broker的时候都使用这个文件中定义的username和password来让对方进行认证。

而user_NAME语句,是用来配置客户端连接Broker时使用的用户名和密码,也就是新建用户的用户名都是以user_开头的,等号后面是密码,密码可以是明文且没有复杂度要求。完整语句是user_USERNAME=“PASSWORD”。

Client部分是用来设置与Zookeeper的连接的,它还允许broker设置 SASL ACL 到zookeeper 节点,锁定这些节点,只有broker可以修改它。如果Zookeeper与Broker之间不设置认证,那么就可以不配置。

创建kafka_client_jaas.conf文件
进入Kafka程序目录的config目录中,执行下面的命令:

touch kafka_client_jaas.confKafkaClient {org.apache.kafka.common.security.plain.PlainLoginModule required
username="admin"
password="admin";
};
Client {org.apache.zookeeper.server.auth.DigestLoginModule required
username="admin"
password="admin";
};

这个文件是客户端连接Broker使用的,username和password是用来配置客户端连接broker的用户,在上面配置中,客户端使用admin用户连接到broker。

这些客户端包括kafka的二进制包中bin目录下的客户端工具以及其他外部客户端,比如Java、Python程序等。

内部客户端工具
kafka自带的生产和消费客户端工具

比如下面的客户端工具:

kafka-console-consumer.sh
kafka-console-producer.sh
kafka-consumer-groups.sh

针对kafka-console-consumer.sh和kafka-console-producer.sh,可以在consumer.properties和producer.properties,加入下面的内容:

security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
在kafka-console-consumer.sh和kafka-console-producer.sh中添加:export KAFKA_OPTS=" -Djava.security.auth.login.config=/data/kafka/kafka_2.11-1.1.0/config/kafka_client_jaas.conf"

目的是让客户端启动时带上身份信息,也就是它使用的用户名和密码

输入命令,启动生产者:

./kafka-console-producer.sh --broker-list x.x.x.x:9092 --topic test --producer.config ../config/producer.properties

输入命令,启动消费者:

./kafka-console-consumer.sh --bootstrap-server x.x.x.x:9092 --topic test --from-beginning --consumer.config ../config/consumer.properties

这两个加上…/config/consumer.properties这个的目的是设置认证协议。这个东西要和Broker端设置的一样。

还有另外一种设置,我们在启动命令行生产者和消费者时不需要引入外部文件,只需要在consumer.properties和producer.properties中加入下面的内容,这样就不需要建立kafka_client_jaas.conf文件:

security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username="admin" password="admin";

注意上面的sasl.jaas.config后面要加分号。

kafka-consumer-groups.sh工具

直接启动会拒绝。针对kafka-consumer-groups.sh工具你可以单独写一个配置文件,包含上面的内容,在启动程序的时候加上一个参数引入这个文件即可,比如:

touch sasl.propertiessecurity.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
./kafka-consumer-groups.sh --bootstrap-server X.X.X.X:9092 --list --command-config ../config/sasl.properties

外部客户端工具

Pythonconfig._kwargs = {"bootstrap_servers": "x.x.x.x:9092","client_id": "ClientId","group_id": "GroupID","enable_auto_commit": False,"auto_offset_reset": "latest","key_deserializer": lambda m: json.loads(m.decode('utf-8')),"value_deserializer": lambda m: json.loads(m.decode('utf-8')),# 配置验证信息"security_protocol": "SASL_PLAINTEXT","sasl_mechanism": "PLAIN","sasl_plain_username": "rex","sasl_plain_password": "123456",
}try:self._consumer = KafkaConsumer(**config._kwargs)
except Exception as err:print("Consumer init failed, %s" % err)

security_protocol:与Borker通信协议,默认是PLAINTEXT,可选值为:PLAINTEXT, SSL,SASL_PLAINTEXT。

sasl_mechanism:当security_protocol被配置为SASL_PLAINTEXT或者SASL_SSL时,该参数的可用值为PLAIN、GSSAPI、OAUTHBEARER。

sasl_plain_usernam和sasl_plain_password,设置SASL PLAIN认证使用的用户名和密码,这个信息就是在Broker使用的kafka_server_jaas.conf文件中配置的。如果sasl_mechanism设置成PLAIN的话,这两个必须配置。

生产者和消费者都是这么配置,至于这个用户有什么权限,比如读、写等需要在服务端设置ACL。如果遇到check_version错误,则在配置中需要制定版本api_version=(0,10)。

Java

方式一:

Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, “node01:9092”);
props.put(“acks”, “all”);
props.put(“retries”, 0);
props.put(“batch.size”, 16384);
props.put(“linger.ms”, 1);
props.put(“buffer.memory”, 33554432);
props.put(“key.serializer”, “org.apache.kafka.common.serialization.StringSerializer”);
props.put(“value.serializer”, “org.apache.kafka.common.serialization.StringSerializer”);// 这里设置SASL连接
props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, “SASL_PLAINTEXT”);
props.put(SaslConfigs.SASL_MECHANISM, “PLAIN”);
props.put(“sasl.jaas.config”,
“org.apache.kafka.common.security.plain.PlainLoginModule required username=\”alice\” password=\”123456\”;”);

方式二:

System.setProperty("java.security.auth.login.config", "/tmp/kafka_client_jaas.conf"); //配置文件路径
props.put("security.protocol", "SASL_PLAINTEXT");
props.put("sasl.mechanism", "PLAIN");
而上面那个文件的内容就是:KafkaClient {org.apache.kafka.common.security.plain.PlainLoginModule requiredusername="alice"password="123456";
};

修改Broker配置文件
在server.properties增加如下内容:

配置listener

listeners=SASL_PLAINTEXT://x-x-x-x:9092
advertised.listeners=SASL_PLAINTEXT://x-x-x-x:9092

认证方面

# 表示Broker间通信使用SASL
security.inter.broker.protocol=SASL_PLAINTEXT# 表示开启PLAIN认证机制
sasl.enabled.mechanisms=PLAIN
# 表示Broker间通信也启用PLAIN机制
sasl.mechanism.inter.broker.protocol=PLAIN# 授权方面
# 设置身份验证使用的类
authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer# 设置超级账号,如果是多个需要分号分割,例如:User:admin;User:root
super.users=User:admin# 对所有用户topic可见,要禁用。
allow.everyone.if.no.acl.found=false

服务端的另外一种配置

Broker还可以使用sasl.jaas.config配置JAAS。字段是:listener.name.{listenerName}.{saslMechanism}.sasl.jaas.config

修改server.propertis文件

listener.name.sasl_plaintext.plain.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \username="admin" \password="admin" \user_admin="admin" \user_tom="123456" \user_alice="123456";

listener.name:固定格式

{listenerName}:就是上面的sasl_plaintext,这里和linsteners中配置的协议要一致。

{saslMechanism}:就是上面的plain

sasl.jaas.config:固定格式

下面是另外一种listener.name,这种是使用sasl的scram,:

listener.name.sasl_plaintext.scram-sha-256.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \username="admin" \password="admin-secret";

所谓listener就是:listeners=SASL_PLAINTEXT://x-x-x-x:9092就是这个语句配置的,因为你可以看到地址前面配置了协议。换句话说Broker可以配置多个验证方式,用逗号分隔即可PLAINTEXT://localhost:9092,SSL://localhost:9091。

注意:如果使用在server.propertis文件中设置JAAS的方式,那么就不用建立kafka_server_jaas.conf文件。不过由于PLAIN形式是基于文件配置的用户名和密码,所以建议使用单独的kafka_server_jaas.conf,毕竟用户多了会造成server.propertis比较乱。对于SCRAM机制的话可以配置在server.propertis里,毕竟它的用户是存放在Zookeeper中。

修改Broker启动脚本
编辑./kafka-server-start.sh增加一个环节变量:

export SECURITY_OPTS="-Djava.security.auth.login.config=/opt/java/kafka/config/kafka_server_jaas.conf"

主要是让kafka-run-class.sh启动脚本加载这个文件。在kafka-run-class.sh增加下面的内容:

KAFKA_OPTS="$SECURITY_OPTS $KAFKA_OPTS"

默认kafka-run-class.sh文件中的$KAFKA_OPTS是空的,如下:

# Generic jvm settings you want to add
if [ -z "$KAFKA_OPTS" ]; thenKAFKA_OPTS=""
fi

所以你可以直接修改这个变量为-Djava.security.auth.login.config=/opt/java/kafka/config/kafka_server_jaas.conf",而不需要建立SECURITY_OPTS环境变量。

说明:如果Broker的JAAS通过在server.properties文件中的sasl.jaas.config参数配置,那么就不需要修改启动脚本。因为修改启动脚本是为了让它去加载外部的JAAS文件,如果这个文件的内容都在Broker启动使用的server.properties文件中配置了,那么在启动的时候就无需加载外部文件了。

配置用户的ACL
列出ACL设置

列出所有主题的ACL设置

kafka-acls.sh --authorizer-properties zookeeper.connect=x.x.x.x:2181/CHROOT --list

列出指定主题的ACL设置

kafka-acls.sh --authorizer-properties zookeeper.connect=x.x.x.x:2181/CHROOT --list --topic TOPIC_NAME

授权用户

# 允许 alice 用户读取和写入test主题
./kafka-acls.sh --authorizer-properties zookeeper.connect=x.x.x.x:2181/CHROOT --add --allow-principal User:alice --operation Read --operation Write --topic test# 允许GroupA组使用alice用户对主题test读写操作
./kafka-acls.sh --authorizer-properties zookeeper.connect=x.x.x.x:2181/CHROOT --add --allow-principal User:alice --operation Read --operation Write --topic test --group GroupA# 允许所有用户对某个主题有读写操作
./kafka-acls.sh --authorizer-properties zookeeper.connect=x.x.x.x:2181/CHROOT --add --allow-principal User:* --consumer --topic test# 拒绝某个主机使用alice账号读写,允许其他所有的主机使用任何账号进行读写某个主题
./kafka-acls.sh --authorizer-properties zookeeper.connect=x.x.x.x:2181/CHROOT --add --allow-principal User:* --allow-host * --deny-principal User:alice --deny-host 198.51.100.3 --consumer --topic test

如果是删除操作就把上面的 --add 改成 --remove。

–operation支持的操作有:READ、WRITE、DELETE、CREATE、ALTER、DESCRIBE、ALL,所以一般我们快捷方式授权:

授权给某个消费者组读取和订阅权限就直接使用–consumer参数而不使用–operation来指定,前者就包含了允许消费者在主题上READ、DESCRIBE以及在消费者组在主题上READ。
授权给某个消费者组写和订阅权限就直接使用–producer参数,它包括了生产者对主题有写和订阅权限以及在集群上建立主题的权限。

# 快捷设置允许某个组使用某用户对某主题读操作
./kafka-acls.sh --authorizer-properties zookeeper.connect=x.x.x.x:2181/CHROOT --add --allow-principal User:alice --consumer --topic test --group GroupA# 快捷设置允许某用户对某主题写操作
./kafka-acls.sh --authorizer-properties zookeeper.connect=x.x.x.x:2181/CHROOT --add --allow-principal User:alice --producer --topic test

如果授权用户同上读写那么就要手动设置–operation参数

配置SASL\SCRAM
SASL\SCRAM都属于SASL认证框架范围,它主要解决了PLAIN机制中密码铭文问题以及动态更新问题,解决动态更新用户的机制就是用户信息存放在Zookeeper中。

创建kafka_server_jaas.conf文件

KafkaServer {org.apache.kafka.common.security.scram.ScramLoginModule required
username="admin"
password="admin";
};

这个文件的作用上面以及说过了,不过在这种SASL\SCRAM机制下,这个文件只需要配置这个部分,因为用户信息在Zookeeper中。

修改Broker配置文件

# 设置监听使用SASL而不是SSL
listeners=SASL_PLAINTEXT://172.16.247.100:9092
advertised.listeners=SASL_PLAINTEXT://172.16.247.100:9092# Zk连接设置
zookeeper.connect=172.16.247.100:2181/kafka# 认证部分
# 表示开启SCRAM认证机制,并启用SHA-256算法
sasl.enabled.mechanisms=SCRAM-SHA-256
# 表示Broker间通信也要开启SCRAM认证,同样适用SHA-256算法
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-256
# 表示Broker间通信使用SASL
security.inter.broker.protocol=SASL_PLAINTEXT#
listener.name.sasl_plaintext.scram-sha-256.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \username="admin" \password="admin";# 授权方面
# 设置身份验证使用的类
authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer# 设置超级账号,如果是多个需要分号分割,例如:User:admin;User:root
super.users=User:admin# 对所有用户topic可见,要禁用。
allow.everyone.if.no.acl.found=false

这里我通过sasl.jaas.config这种方式来配置,那么上面的kafka_server_jaas.conf这个文件就可以不用,之所以写主要是为了说明一下,如果你希望通过使用外部文件的方式那么你就需要这个文件,并且启动时修改启动脚本增加环境变量来引用这个文件。

请注意这里的ZK连接设置,我这里使用了chroot,172.16.247.100:2181/kafka,指定了一个路径,这个路径要提前在ZK中创建,create /kafka kafka。

说明:官网这里设置的security.inter.broker.protocol这个参数是SASL_SSL,包括listeners也是SASL_SSL,需要说明一下如果你启用了SSL加密通信的话你就设置,如果你没有启用那么就设置SASL_PLAINTEXT就好。

修改Broker启动脚本
如果使用外部kafka_server_jaas.conf文件方式,则需要修改启动脚本,把下面的环境变量添加到kafka-server-start.sh脚本中。如果采用配置方式则无需修改脚本。

export SECURITY_OPTS="-Djava.security.auth.login.config=/work/kafka_2.11-2.3.0/config/kafka_server_jaas.conf"
export KAFKA_OPTS="$SECURITY_OPTS $KAFKA_OPTS"
创建用户
添加三个用户

./kafka-configs.sh --zookeeper localhost:2181/kafka --alter --add-config 'SCRAM-SHA-256=[password=admin],SCRAM-SHA-512=[password=admin]' --entity-type users --entity-name admin./kafka-configs.sh --zookeeper localhost:2181/kafka --alter --add-config 'SCRAM-SHA-256=[password=123456],SCRAM-SHA-512=[password=123456]' --entity-type users --entity-name tom./kafka-configs.sh --zookeeper localhost:2181/kafka --alter --add-config 'SCRAM-SHA-256=[password=123456],SCRAM-SHA-512=[password=123456]' --entity-type users --entity-name lucy

创建用户时ZK的连接路径也要写上chroot,如果你使用了chroot的话。如果你kafka配置中写了,而这里创建用户没有写,那么你启动kafka集群就会报验证失败的错误。

另外再说一下为什么要创建admin用户,在配置文件sasl.jaas.config中或者是kafka_server_jaas.conf文件中的KafkaServer字段,定义了Broker间连接使用的用户名和密码,这个用户名和密码可以是你自己定义的,不一定是admin,这只是一个名字。另外这里只定义了Broker连接使用的用户名和密码,但是不是创建,所以之后我们要创建这个用户,所以就是上面的语句为什么要创建admin账号。即使是单台单实例的场景下,Broker启动会连接ZK,如果启用了SASL,那么它会使用配置的账号到ZK中去验证。/KAFKA_CHROOT/config/users/节点下存放着用户。

查看所有用户

./kafka-configs.sh --zookeeper localhost:2181 --describe --entity-type users

创建主题
创建主题的时候有两种方式一个是使用–zookeeper和–bootstrap-server,前者不需要认证因为它不连接broker,但是后者需要。

创建文件kafka_client_jaas.conf

创建主题的命令也是客户端,你broker配置了认证,那么这个客户端工具连接broker需要携带认证信息,这里配置的就是客户端使用的用户名和密码,这里我们就使用之前创建的admin

KafkaClient {org.apache.kafka.common.security.scram.ScramLoginModule requiredusername="admin"password="admin";
};

创建文件adminclient-configs.conf

内容如下:这里的设置要和broker配置的认证方式一致

security.protocol=SASL_PLAINTEXT
sasl.mechanism=SCRAM-SHA-256

修改kafka-topics.sh脚本内容

添加如下内容:

export KAFKA_OPTS="-Djava.security.auth.login.config=/work/kafka_2.11-2.3.0/config/kafka_client_jaas.conf"

运行kafka-topics.sh命令

./kafka-topics.sh --list --bootstrap-server 172.16.42.100:9092 --command-config ../config/adminclient-configs.conf

命令行工具测试生产和消费
修改consumer.properties配置文件

security.protocol=SASL_PLAINTEXT
sasl.mechanism=SCRAM-SHA-256
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username="lucy" password="123456";

修改producer.properties配置文件

security.protocol=SASL_PLAINTEXT
sasl.mechanism=SCRAM-SHA-256
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username="tom" password="123456";

配置ACL
这个和之前是一致的,所以不再进行说明。

Kafka在什么时候会检测权限
kafka授权,如果使用**非管理账号*,程序启动会连接broker来获取元数据,从metadata返回的topic列表时,也是根据acl过滤过的,也就是这个账号没有读取某个主题的权限,那么返回的列表中将不会有这个主题。

我们工作中有一个kafka监控程序,用于监控消费者的偏移量,使用的是一个开源的go开发的exporter,它会读取broker的元数据以及消费__consumer_offsets主题。我们使用的非管理账号,在授权的时候我们给这个账号授予所有主题的读取权限,因为通过读取__consumer_offsets获取主题的消费者偏移量,也会受到你所使用账号是不是对某个主题有读取权限的限制。所以如果使用非管理账号那么最好的办法就是授权该账号对所有主题具有读权限。

参考文档
Kafka验证配置实例

【Kafka】Kafka认证与授权相关推荐

  1. Kafka动态认证SASL/SCRAM配置+整合springboot配置

    记录: zookeeper启动命令: [root@master-yzjgxh2571705819-1651919082731-99-0727183 bin]# ./zkServer.sh start ...

  2. Kafka动态认证SASL/SCRAM验证

    一.目的 配置SASL/PLAIN验证,实现了对Kafka的权限控制.但SASL/PLAIN验证有一个问题:只能在JAAS文件KafkaServer中配置用户,一但Kafka启动,无法动态新增用户.S ...

  3. 开启kafka密码认证

    Kafka默认未开启密码认证,可以免密登录,太不安全,因此需要开启密码认证. 一 kafka认证方式类型 kafka提供了多种安全认证机制,主要分为SSL和SASL大类.其中SASL/PLAIN是基于 ...

  4. python子进程进行kinit认证_使用kafka-python客户端进行kafka kerberos认证

    之前说过python confluent kafka客户端做kerberos认证的过程,如果使用kafka python客户端的话同样也可以进行kerberos的认证,具体的认证机制这里不再描述,主要 ...

  5. kafka身份认证 maxwell_Kafka 使用SASL / SCRAM进行身份验证

    使用SASL / SCRAM进行身份验证 请先在不配置任何身份验证的情况下启动Kafka 1. 创建SCRAM Credentials 1.1 创建broker通信用户(或称超级用户) bash Em ...

  6. kafka权限认证ssl

    2016-11-14 18:16:01 shengjk1 阅读数 18141更多 分类专栏: 工作之行 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和 ...

  7. Kafka安全认证SASL/PLAINTEXT,账号密码认证

    环境centos7 kafka集群和zookeeper集群默认都是不带用户密码的. 1. 配置zookeeper集群SASL zookeeper所有节点都是对等的,只是各个节点角色可能不相同.以下步骤 ...

  8. 大数据Hadoop之——Kafka安全机制(Kafka SSL认证实现)

    文章目录 一.概述 1)SASL认证概述 2)Delegation Token认证概述 3)SSL认证概述(本章实现) 二.各种安全认证机制对比和使用场景 三.Kafka SSL认证实现 1)创建ss ...

  9. EMR集群安全认证和授权管理

    简介:介绍EMR高安全集群如何使用Kerberos和Apache Ranger进行鉴权和访问授权管理 直达最佳实践:[EMR集群安全认证和授权管理] 最佳实践频道:[点击查看更多上云最佳实践] 这里有 ...

最新文章

  1. 校园音乐点歌平台的设计与开发 微信小程序 点歌系统 java 开发
  2. Python使用matplotlib可视化斜率图、对比同一数据对象前后(before、after)两个状态的差异(Slope Chart)
  3. Comparative assessment of long-read error-correction software applied to RNA-sequencing data
  4. java lambda循环_使用Java 8 Lambda简化嵌套循环
  5. Web Service实现分布式服务的基本原理
  6. C#的多线程机制探索2
  7. LeetCode--85.最大矩形(单调栈)
  8. System.Windows.Forms.ListView
  9. python提取数组元素_python简单获取数组元素个数的方法
  10. javascript调用ActiveX接口失败的解决方案及使用心得
  11. redis简单使用1
  12. 学习语文必须掌握的知识点思维导图
  13. 锻造成形与计算机技术,铸造成型及控制工程
  14. 学习excel的使用技巧复制一列文本成新列去重
  15. Dockerfile说明
  16. 【ML on Kubernetes】第 3 章:探索 Kubernetes
  17. matlab程序算天气,科学网-站点气温数据的积温计算(含Matlab程序实现)-朱永超的博文...
  18. 小鱼鱼的 Python 学习笔记(第一周)
  19. 假面舞会狂欢节·朗瀚威 | 艺术品化的meme:以传播促进流通
  20. vue-cli3.0+webpack4中关于svg-sprite-loader踩坑,让svg组件徜徉我的web项目

热门文章

  1. 胡润百富:华为成为中国最值钱消费电子企业 小米排名第二
  2. 京东方将首次向华为供应on-cell OLED面板 用于Mate 40系列
  3. iPhone 12售价再曝光,可能涨价50美元
  4. 《俄罗斯方块》正版授权手游开启预约:支持QQ、微信双平台
  5. 游戏股的年过完了,盈利下滑,有企业靠卖房维持业绩
  6. 带刺的下沉市场:小镇青年要的不止是9块9包邮
  7. __FILE__, __LINE__, __FUNCTION__
  8. Android 完整漂亮问卷、试卷 -- 支持单选、判断、不定项
  9. Springboot starter开发之traceId请求日志链路追踪
  10. 史上最详细JVM笔记