在40岁老架构师尼恩的(50+)读者社群中,最近小伙伴,面试央企、美团、京东、阿里、 百度、头条等大厂。
下面是一个小伙伴成功拿到通过了一个央企设计研究院一面面试,现在把面试真题和参考答案收入咱们的宝典。
通过央企一面真题, 大家可以看看,收个优质央企Offer需要学点啥?
总之,光代码漂亮不够, 面试,还得会吹。
这里把题目以及答案,经过整理和梳理之后,收入咱们的《尼恩Java面试宝典PDF》 V126版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发、吹牛水平。
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到文末公众号【技术自由圈】获取
前天,小伙伴面试央企一个设计研究院, 遇到了几个核心难题, 找尼恩来求助。
在 Kubernetes(K8s)中,网络隔离可以通过使用不同的Network Policies 网络策略和适当的 CNI 插件来实现。
网络策略是 Kubernetes 的一个核心功能,它允许管理员控制 Pod 之间的网络通信。
使用 Network Policies 可以灵活地控制 Pod 之间的网络通信,而使用CNI 插件如Calico 可以提供额外的网络隔离功能。
同时,你可以使用 Kubernetes Java 客户端库来管理这些策略。
Kubernetes 支持使用 Network Policies 来控制 Pod 之间的网络通信。
Network Policies 允许你定义规则,以允许或拒绝特定命名空间中的 Pod 之间的通信。
例如,以下是一个简单的 Network Policy,它拒绝从命名空间 ns1
到命名空间 ns2
的所有网络通信:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: ns1
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
你还可以使用 podSelector
来选择特定的 Pod,并使用 ingress
或 egress
规则来允许或拒绝这些 Pod 与其他 Pod 的通信。
CNI(Container Network Interface)是一个标准,它定义了 Kubernetes 如何与网络插件交互。
Calico 是一个常见的 Kubernetes CNI 插件,它也提供了一种强大的方式来控制网络隔离。
Calico 支持使用 Calico 网络策略来定义网络规则。
例如,以下是一个简单的 Calico 网络策略,它允许从命名空间 ns1
到命名空间 ns2
的所有网络通信:
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: allow-all
namespace: ns1
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
你还可以使用 podSelector
来选择特定的 Pod,并使用 ingress
或 egress
规则来允许或拒绝这些 Pod 与其他 Pod 的通信。
在 Java 应用程序中,可以使用 Kubernetes Java 客户端库来创建和管理 Network Policies。
以下是一个简单的 Java 代码片段,它展示了如何使用 Kubernetes Java 客户端库来创建一个 Network Policy:
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.Configuration;
import io.kubernetes.client.openapi.apis.NetworkingV1Api;
import io.kubernetes.client.openapi.models.V1NetworkPolicy;
import java.io.IOException;
public class NetworkPolicyExample {
public static void main(String[] args) throws IOException, ApiException {
ApiClient client = Configuration.getDefaultApiClient();
NetworkingV1Api api = new NetworkingV1Api(client);
V1NetworkPolicy policy = new V1NetworkPolicy();
policy.setMetadata(null);
policy.setSpec(null);
// Set the desired network policy spec
policy.getSpec().setPodSelector("");
policy.getSpec().setPolicyTypes(Arrays.asList("Ingress", "Egress"));
// Create the network policy
api.createNamespacedNetworkPolicy("ns1", policy);
}
}
这个代码片段创建了一个空的 Network Policy,你可以根据需要修改它。
尼恩作为技术中台的负责人,曾经主导了 网关平台的架构和设计工作。
网关平台可以基于 成熟的网关如 kong、 springcloud-gateway 进行扩展,二次开发。
并且也进行过基于 kong、 springcloud-gateway 进行扩展,二次开发的预研, 并且基本实现了 代理 、转发的功能。
如果使用 springcloud-gateway进行 扩展, 是可以进行 路由规则的外部加载的, 可以从 redis、db 加载路由规则,设计和实现一个自己的 RouteDefinitionRepository 路由定义仓库 就OK了
从redis 加载路由规则的 参考代码如下
@Component
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
public static final String GATEWAY_ROUTES = "geteway_routes";
@Resource
private StringRedisTemplate redisTemplate;
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
List<RouteDefinition> routeDefinitions = new ArrayList<>();
redisTemplate.opsForHash().values(GATEWAY_ROUTES).stream()
.forEach(routeDefinition -> routeDefinitions.add(JSON.parseObject(routeDefinition.toString(), RouteDefinition.class)));
return Flux.fromIterable(routeDefinitions);
}
}
springcloud-gateway 启动的时候,会进行 RouteDefinitionRepository 仓库的创建,如果自己义了,就使用 自定义的
如果没有自定义,就默认用InMemoryRouteDefinitionRepository,这缓存了从配置文件读取的路由规则。
而做动态路由的关键就在这里。
即通过自定义的RouteDefinitionRepository类,来提供路由配置信息。替代 默认的 InMemoryRouteDefinitionRepository ,就OK了。
所以,也比较简单。
springcloud gateway 的路由规则,可以从 外部数据源加载, 同样可以从nacos 加载。
同样,尼恩也基于kong,做过网关平台的预研, kong使用lua+nginx, lua语音比较简单,nginx性能高,也是实现网关平台的较好的选择。
但是,无论是kong、还是 springcloud-gateway , 开发的时候, 比较难以找到熟练的开发人员。
kong lua 开发人员本来少, 人难找, 大家也不愿意使用lua开发。
springcloud-gateway 使用 响应式编程, 这种编程模式和命令式相比,思维模式很不人性化, 执行流程跳跃性太强, 调试的时候,往往不知道下一步去了哪里, 生手更头疼。 这个人更难找、
或者说,就是尼恩会开发, 但也不可能一个人啥都干了。
所以,尼恩在做技术选型的时候,既没有使用 springcloud-gateway ,也没有使用kong,二是基于netty 去设计 api 网关平台。
性能高不说,人也好找。
如何使用 netty 去设计一个api 网关平台,具体请参见尼恩的第33章视频,这个是一个绝对的 面试黄金项目,简历黄金项目。
在 Java 中,JVM(Java Virtual Machine)的监控主要涉及对 JVM 内部状态和资源的使用情况进行监控和管理,以便在必要时对 JVM 进行优化和调整。
JVM 提供了一系列的参数,可以通过这些参数来控制和监控 JVM 的行为。例如,可以使用 -verbose:gc
参数来开启垃圾回收的详细输出,从而了解 GC 的频率、时间和回收的垃圾对象数量等信息。
另一个例子是,可以使用 -Xmx
参数来设置 JVM 最大允许的堆内存大小,从而限制堆内存的使用量。
JConsole 和 VisualVM 是两个常用的图形化工具,用于监控和分析 JVM 的性能。它们可以显示 JVM 的各种指标,如 CPU 使用率、线程栈信息、死锁和垃圾回收等。
Java 代码可以通过一些 API 来获取 JVM 的信息。例如,可以使用 ManagementFactory
类来获取 JVM 的内存使用情况、线程栈信息等。
下面是一个简单的 Java 代码示例,展示了如何使用 ManagementFactory
类来获取 JVM 的内存使用情况:
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.ManagementFactory;
public class JVMMonitor {
public static void main(String[] args) {
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage();
System.out.println("Used Memory: " + memoryUsage.getUsed());
System.out.println("Committed Memory: " + memoryUsage.getCommitted());
}
}
JVMTI(Java Virtual Machine Tool Interface)是 JVM 提供的一套用于监控和控制 JVM 的接口。它允许开发人员创建自己的监控和分析工具,以定制的方式来监控 JVM。
JVM 参数监控的原理很简单,JVM 通过读取命令行参数或配置文件中的参数来改变其行为。
当 JVM 启动时,它会解析这些参数,并相应地调整其内部状态和资源使用。
JConsole 和 VisualVM 的工作原理是利用 JVMTI 接口来获取 JVM 的各种信息。它们通过 JVMTI 接口向 JVM 发送请求,以获取所需的监控数据,并将其以可视化的方式呈现给用户。
JVMTI(Java 虚拟机工具接口、Java Virtual Machine Tool Interface,JVMT)是JVM提供了一种编程接口,
JVMTI 允许软件开发人员创建软件代理以监视和控制 Java 编程语言应用程序。
JVMTI 是 Java 2 Software Development Kit (SDK), Standard Edition, 版本 1.5.0 中的一种新增功能。
JVMTI 它取代了 Java Virtual Machine Profiling Interface (JVMPI),从版本 1.1 起即作为 Java 2 SDK 的一种实验功能包括在内。
在 JSR-163 中对 JVMTI 进行了有关说明。
JVMTI 的原理是,在 JVM 启动时,JVMTI 驱动程序会加载到 JVM 中,并创建一个 JVMTI 接口的实例。
开发人员可以使用 JVMTI 接口提供的方法来获取 JVM 的各种信息,如垃圾回收数据、线程栈信息等。
JMX 全称为 Java Management Extensions,翻译过来就是 Java 管理扩展,用来管理和监测 Java 程序。
最常用到的就是对于 JVM 的监测和管理,比如 JVM 内存、CPU 使用率、线程数、垃圾收集情况等等。
另外,还可以用作日志级别的动态修改,比如 log4j 就支持 JMX 方式动态修改线上服务的日志级别。
最主要的还是被用来做各种监控工具,常用的 Spring Boot Actuator、JConsole、VisualVM 等JVM监控工具,就是通过 JMX来实现。
Java 代码监控的原理是利用 ManagementFactory
类提供的 API 来获取 JVMTI 数据。ManagementFactory
类是 JVMTI 的一层包装,它将 JVMTI 的复杂性隐藏在简单的 Java 接口后面。
JMX 既是 Java 管理系统的一个标准,一个规范,也是一个接口,一个框架。有标准、有规范是为了让开发者可以定制开发自己的扩展功能,而且作为一个框架来讲,JDK 已经帮我们实现了常用的功能,尤其是对 JVM 的监控和管理。
grafana+prometheus+jmx
访问Grafana查看JVM面板,获得如下效果:
监控 JVM 的方法有很多,每种方法都有其优缺点。
开发人员应根据具体的应用场景和需求来选择合适的监控方法。在实际开发中,通常会结合多种方法来监控 JVM,以获取更全面和准确的 JVM 状态和性能信息。
三种方法:
(1)服务端 nacos 隔离
(2)服务端 用户 隔离
(3)客户端 配置 隔离
为dev, test,prod 启动 不同的 nacos 实例, 然后通过 环境变量 获取nacos 的 地址。
dev 环境, 配置的 是 dev 类型的nacos 实例
pod 类型的nacos 实例 的地址, 不对开发同学暴露。
这种做了最为 彻底的 保密工作。 保证生产环境安全
dev, test,prod 环境 共用nacos
为dev, test,prod 启动 不同的 nacos 用户, 然后通过 不同的用户, 获取不同环境的 配置。
dev 环境, 配置的 是 dev 类型的nacos 用户 去访问 nacos
test环境, 配置的 是 test类型的nacos 用户 去访问 nacos
prod 环境, 配置的 是 prod 类型的nacos 用户 去访问 nacos
客户端 可以采用以下方法:
dev
、test
和 prod
环境创建名为 NACOS_SERVER_ADDRESS
的环境变量,分别指向各自的环境地址。System.setProperty()
方法来为不同的环境设置不同的 Nacos 地址。这需要你在运行应用程序时传递相应的参数。application-dev.properties
、application-test.properties
和 application-prod.properties
。这些文件可以包含 Nacos 的地址和其他相关配置。在运行应用程序时,使用 spring.config.location
参数来指定相应的配置文件。application.yml
或 application.properties
文件中使用 spring.profiles.active
属性来选择要激活的配置。import java.util.Properties;
public class NacosConfig {
public static void main(String[] args) {
// 根据环境设置 Nacos 地址
String nacosAddress;
if (System.getProperty("env") == null || System.getProperty("env").equals("dev")) {
nacosAddress = "localhost:8848";
} else if (System.getProperty("env").equals("test")) {
nacosAddress = "test-nacos-server:8848";
} else if (System.getProperty("env").equals("prod")) {
nacosAddress = "prod-nacos-server:8848";
} else {
throw new RuntimeException("Invalid environment");
}
// 使用 NacosAddress
System.out.println("Nacos server address: " + nacosAddress);
}
}
在运行应用程序时,你可以使用 -Denv=dev
、-Denv=test
或 -Denv=prod
参数来选择要使用的环境。
上述方法可以确保你在本地开发环境中使用正确的 Nacos 内容,而不会影响到其他环境。当然,具体实现可能会根据你的项目结构和使用的工具而有所不同。
Nginx
和 Keepalive
是两个不同的软件,但它们可以一起使用,以提供高可用性、负载均衡和缓存等优势。下面,我将分别简要介绍这两个软件,然后探讨它们是如何一起设计的。
什么是 Nginx?
Nginx
是一个高性能的 HTTP 和反向代理服务器。它用于 HTTP 服务器、反向代理、负载均衡和 HTTP 缓存。
Nginx 的优势
什么是 Keepalive?
Keepalive
是一个支持集群的高可用性解决方案,主要用于数据库、队列服务和消息服务。
Keepalive 的优势
设计目的
Nginx
和 Keepalive
的结合旨在提供高可用性、高性能的 Web 应用程序。Nginx
用于处理 HTTP 请求,而 Keepalive
用于确保服务器的可靠性。
工作原理
Nginx
。Nginx
接收请求,并根据负载均衡策略,将请求分发给后端服务器。Nginx
。Nginx
接收响应,并将其返回给客户端。Keepalive
会自动将其从服务列表中移除,并尝试重启它。在网络安全和性能优化领域,除了 Nginx 之外,还有许多其他代理软件和硬件设备。以下是一些常见的代理软件和硬件:
这些代理软件和硬件设备根据其特点和功能,在不同的场景中发挥作用。在实际应用中,可以根据需求和预算选择合适的代理软件或硬件设备。同时,为了确保数据安全和高可用性,还可以将这些代理与其他安全措施(如身份验证、访问控制等)结合使用。
在计算机科学中,加密算法是用于将数据转换为一种秘密形式的数学函数。它使得只有授权方能够访问原始数据,从而保护数据的机密性和安全性。
常见的加密算法包括:
这些加密算法根据其特点和安全性在不同的场景中发挥作用。在实际应用中,通常会根据需求和安全性要求选择合适的加密算法。同时,为了确保数据安全,还需要结合其他安全措施,如身份验证、访问控制等。
非对称加密既然也有缺陷,那我们就将对称加密,非对称加密两者结合起来,取其精华、去其糟粕,发挥两者的各自的优势:
这是个非常非常经典的数据传输过程,也是Https传输协议里面最经典的部分。也是把对称加密和非对称加密的作用发挥到了很好的地方。
在https传输的过程中,如果单独只用对称加密,或者单独使用非对称加密都会出现问题。
关于加密算法的实操,具体请参见尼恩的 《Java高并发核心编程 卷1 加强版》
-Xms
和-Xmx
参数设置堆内存的大小。-XX:NewRatio
和-XX:SurvivorRatio
参数。-XX:+UseG1GC
和-XX:+UseParallelGC
参数。优化代码。这包括:
监控和分析内存使用情况。使用Java内置的工具(如jconsole
、jvisualvm
等)或第三方工具(如YourKit、MAT等)来分析内存使用情况。
考虑使用分布式缓存系统(如Redis、Memcached等)来减轻应用服务器的负担。
大厂一般都重视算法。
尼恩给大家备好了100道常背的算法题, 大家要一定要吃透,温故而知新, 常常看看, 不要忘了。
在尼恩的(50+)读者社群中,很多、很多小伙伴需要进大厂、拿高薪。
尼恩团队,会持续结合一些大厂的面试真题,给大家梳理一下学习路径,看看大家需要学点啥?
前面用多篇文章,给大家介绍阿里、百度、字节、滴滴的真题:
《赢麻了……腾讯1面核心9问,小伙伴过了提42W offer》
这些真题,都会收入到 史上最全、持续升级的 PDF电子书 《尼恩Java面试宝典》。
本文收录于 《尼恩Java面试宝典》。
基本上,把尼恩的 《尼恩Java面试宝典》吃透,大厂offer很容易拿到滴。另外,下一期的 大厂面经大家有啥需求,可以发消息给尼恩。
……完整版尼恩技术圣经PDF集群,请找尼恩领取
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓