首页 文章 精选 留言 我的

精选列表

搜索[面试],共4913篇文章
优秀的个人博客,低调大师

JAVA面试核心教程|Java面试基础知识点总结

Java中的原始数据类型都有哪些,它们的大小及对应的封装类是什么? byte——1 byte——Byte short——2 bytes——Short int——4 bytes——Integer long——8 bytes——Long float——4 bytes——Float double——8 bytes——Double char——2 bytes——Character boolean——————Boolean boolean数据类型非true即false。 这个数据类型表示1 bit,但是它的大小并没有精确定义。 《Java虚拟机规范》中如是说:“虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位”。这样我们可以得出boolean类型单独使用是4个字节,在数组中又是1个字节。 那虚拟机为什么要用int来代替boolean呢?为什么不用byte或short,这样不是更节省内存空间吗? 实际上,使用int的原因是,对于当下32位的CPU来说,一次进行32位的数据交换更加高效。 综上,我们可以知道:官方文档对boolean类型没有给出精确的定义,《Java虚拟机规范》给出了“单独时使用4个字节,boolean数组时1个字节”的定义,具体还要看虚拟机实现是否按照规范来,所以1个字节、4个字节都是有可能的。这其实是一种时空权衡。 boolean类型的封装类是Boolean。 大家可以点击加入群:【Java高级架构进阶群】:854180697 里面有Java高级大牛直播讲解知识点 走的就是高端路线 (如果你想跳槽换工作 但是技术又不够 或者工作上遇到了瓶颈 我这里有一个JAVA的免费直播课程 讲的是高端的知识点基础不好的误入哟 只要你有1-5年的开发经验可以加群找我要课堂链接 注意:是免费的 没有开发经验误入哦) 谈一谈”==“与”equals()"的区别。 《Think in Java》中说:“关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系”。 "=="判断的是两个对象的内存地址是否一样,适用于原始数据类型和枚举类型(它们的变量存储的是值本身,而引用类型变量存储的是引用);equals是Object类的方法,Object对它的实现是比较内存地址,我们可以重写这个方法来自定义“相等”这个概念。比如类库中的String、Date等类就对这个方法进行了重写。 综上,对于枚举类型和原始数据类型的相等性比较,应该使用"==";对于引用类型的相等性比较,应该使用equals方法。 Java中的四种引用及其应用场景是什么? 强引用: 通常我们使用new操作符创建一个对象时所返回的引用即为强引用 软引用: 若一个对象只能通过软引用到达,那么这个对象在内存不足时会被回收,可用于图片缓存中,内存不足时系统会自动回收不再使用的Bitmap 弱引用: 若一个对象只能通过弱引用到达,那么它就会被回收(即使内存充足),同样可用于图片缓存中,这时候只要Bitmap不再使用就会被回收 虚引用: 虚引用是Java中最“弱”的引用,通过它甚至无法获取被引用的对象,它存在的唯一作用就是当它指向的对象回收时,它本身会被加入到引用队列中,这样我们可以知道它指向的对象何时被销毁。 object中定义了哪些方法? clone() equals() hashCode() toString() notify() notifyAll() wait() finalize() getClass() hashCode的作用是什么? 请参考散列表的基本原理与实现 ArrayList, LinkedList, Vector的区别是什么? ArrayList:内部采用数组存储元素,支持高效随机访问,支持动态调整大小 LinkedList:内部采用链表来存储元素,支持快速插入/删除元素,但不支持高效地随机访问 Vector: 可以看作线程安全版的ArrayList String, StringBuilder, StringBuffer的区别是什么? String: 不可变的字符序列,若要向其中添加新字符需要创建一个新的String对象 StringBuilder: 可变字符序列,支持向其中添加新字符(无需创建新对象) StringBuffer: 可以看作线程安全版的StringBuilder Map, Set, List, Queue、Stack的特点及用法。 Map:Java中存储键值对的数据类型都实现了这个接口,表示“映射表”。支持的两个核心操作是get(Object key)以及put(K key, V value),分别用来获取键对应的值以及向映射表中插入键值对。 Set:实现了这个接口的集合类型中不允许存在重复的元素,代表数学意义上的“集合”。它所支持的核心操作有add(E e), remove(Object o), contains(Object o),分别用于添加元素,删除元素以及判断给定元素是否存在于集中。 List: Java中集合框架中的列表类型都实现了这个接口,表示一种有序序列。支持get(int index), add(E e)等操作。 Queue:Java集合框架中的队列接口,代表了“先进先出”队列。支持add(E element),remove()等操作。 Stack:Java集合框架中表示堆栈的数据类型,堆栈是一种“后进先出”的数据结构。支持push(E item), pop()等操作。 更详细的说明请参考官方文档,对相关数据结构不太熟悉的同学可以参考《算法导论》或其他相关书籍。 HashMap和HashTable的区别 HashTable是线程安全的,而HashMap不是 HashMap中允许存在null键和null值,而HashTable中不允许 HashMap的实现原理 简单的说,HashMap的底层实现是“基于拉链法的散列表”。 详细分析请参考 Map源码解析之HashMap源码分析 ConcurrentHashMap的实现原理 ConcurrentHashMap是支持并发读写的HashMap,它的特点是读取数据时无需加锁,写数据时可以保证加锁粒度尽可能的小。由于其内部采用“分段存储”,只需对要进行写操作的数据所在的“段”进行加锁。关于ConcurrentHashMap底层实现的详细分析请参考 Java并发编程:并发容器之ConcurrentHashMap TreeMap, LinkedHashMap, HashMap的区别是什么? HashMap的底层实现是散列表,因此它内部存储的元素是无序的; TreeMap的底层实现是红黑树,所以它内部的元素的有序的。排序的依据是自然序或者是创建TreeMap时所提供的比较器(Comparator)对象。 LinkedHashMap可以看作能够记住插入元素的顺序的HashMap。 Collection与Collections的区别是什么? Collection是Java集合框架中的基本接口; Collections是Java集合框架提供的一个工具类,其中包含了大量用于操作或返回集合的静态方法。 对于“try-catch-finally”,若try语句块中包含“return”语句,finally语句块会执行吗? 会执行。只有两种情况finally块中的语句不会被执行: 调用了System.exit()方法; JVM“崩溃”了。 Java中的异常层次结构 Java中的异常层次结构如下图所示: 我们可以看到Throwable类是异常层级中的基类。 Error类表示内部错误,这类错误使我们无法控制的;Exception表示异常,RuntimeException及其子类属于未检查异常,这类异常包括ArrayIndexOutOfBoundsException、NullPointerException等,我们应该通过条件判断等方式语句避免未检查异常的发生。IOException及其子类属于已检查异常,编译器会检查我们是否为所有可能抛出的已检查异常提供了异常处理器,若没有则会报错。对于未检查异常,我们无需捕获(当然Java也允许我们捕获,但我们应该做的事避免未检查异常的发生)。 Java面向对象的三个特征与含义 三大特征:封装、继承、多态。 Override, Overload的含义与区别 Override表示“重写”,是子类对父类中同一方法的重新定义 Overload表示“重载”,也就是定义一个与已定义方法名称相同但签名不同的新方法 接口与抽象类的区别 接口是一种约定,实现接口的类要遵循这个约定; 抽象类本质上是一个类,使用抽象类的代价要比接口大。 接口与抽象类的对比如下: 抽象类中可以包含属性,方法(包含抽象方法与有着具体实现的方法),常量;接口只能包含常量和方法声明。 抽象类中的方法和成员变量可以定义可见性(比如 public、private等);而接口中的方法只能为public(缺省为public)。 一个子类只能有一个父类(具体类或抽象类);而一个接口可以继承一个多个接口,一个类也可以实现多个接口。 子类中实现父类中的抽象方法时,可见性可以大于等于父类中的;而接口实现类中的接口 方法的可见性只能与接口中相同(public)。 静态内部类与非静态内部类的区别 静态内部类不会持有外围类的引用,而非静态内部类会隐式持有外围类的一个引用。 Java中多态的实现原理 所谓多态,指的就是父类引用指向子类对象,调用方法时会调用子类的实现而不是父类的实现。多态的实现的关键在于“动态绑定”。详细介绍请戳 Java动态绑定的内部实现机制 简述Java中创建新线程的两种方法 继承Thread类(假设子类为MyThread),并重写run()方法,然后new一个MyThread对象并对其调用start()即可启动新线程。 实现Runnable接口(假设实现类为MyRunnable),而后将MyRunnable对象作为参数传入Thread构造器,在得到的Thread对象上调用start()方法即可。 简述Java中进行线程同步的方法 volatile: Java Memory Model保证了对同一个volatile变量的写happens before对它的读; synchronized:可以来对一个代码块或是对一个方法上锁,被“锁住”的地方称为临界区,进入临界区的线程会获取对象的monitor,这样其他尝试进入临界区的线程会因无法获取monitor而被阻塞。由于等待另一个线程释放monitor而被阻塞的线程无法被中断。 ReentrantLock: 尝试获取锁的线程可以被中断并可以设置超时参数。 简述Java中具有哪几种粒度的锁 Java中可以对类、对象、方法或是代码块上锁。 给出“生产者-消费者”问题的一种解决方案 使用阻塞队列: public class BlockingQueueTest { private int size = 20; private ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(size); public static void main(String[] args) { BlockingQueueTest test = new BlockingQueueTest(); Producer producer = test.new Producer(); Consumer consumer = test.new Consumer(); producer.start(); consumer.start(); } class Consumer extends Thread{ @Override public void run() { while(true){ try { //从阻塞队列中取出一个元素 queue.take(); System.out.println("队列剩余" + queue.size() + "个元素"); } catch (InterruptedException e) { } } } } class Producer extends Thread{ @Override public void run() { while (true) { try { //向阻塞队列中插入一个元素 queue.put(1); System.out.println("队列剩余空间:" + (size - queue.size())); } catch (InterruptedException e) { } } } } } ThreadLocal的设计理念与作用 ThreadLocal的作用是提供线程内的局部变量,在多线程环境下访问时能保证各个线程内的ThreadLocal变量各自独立。也就是说,每个线程的ThreadLocal变量是自己专用的,其他线程是访问不到的。ThreadLocal最常用于以下这个场景:多线程环境下存在对非线程安全对象的并发访问,而且该对象不需要在线程间共享,但是我们不想加锁,这时候可以使用ThreadLocal来使得每个线程都持有一个该对象的副本。 concurrent包的整体架构 ArrayBlockingQueue, CountDownLatch类的作用 CountDownLatch:允许线程集等待直到计数器为0。适用场景: 当一个或多个线程需要等待指定数目的事件发生后再继续执行。 ArrayBlockingQueue: 一个基于数组实现的阻塞队列,它在构造时需要指定容量。当试图向满队列中添加元素或者从空队列中移除元素时,当前线程会被阻塞。通过阻塞队列,我们可以按以下模式来工作:工作者线程可以周期性的将中间结果放入阻塞队列中,其它线程可以取出中间结果并进行进一步操作。若工作者线程的执行比较慢(还没来得及向队列中插入元素),其他从队列中取元素的线程会等待它(试图从空队列中取元素从而阻塞);若工作者线程执行较快(试图向满队列中插入元素),则它会等待其它线程取出元素再继续执行。 wait(),sleep() 的区别 wait():Object类中定义的实例方法。在指定对象上调用wait方法会让当前线程进入等待状态(前提是当前线程持有该对象的monitor),此时当前线程会释放相应对象的monitor,这样一来其它线程便有机会获取这个对象的monitor了。当其它线程获取了这个对象的monitor并进行了所需操作时,便可以调用notify方法唤醒之前进入等待状态的线程。 sleep():Thread类中的静态方法,作用是让当前线程进入休眠状态,以便让其他线程有机会执行。进入休眠状态的线程不会释放它所持有的锁。 线程池的用法与优势 优势: 实现对线程的复用,避免了反复创建及销毁线程的开销;使用线程池统一管理线程可以减少并发线程的数目,而线程数过多往往会在线程上下文切换上以及线程同步上浪费过多时间。 用法: 我们可以调用ThreadPoolExecutor的某个构造方法来自己创建一个线程池。但通常情况下我们可以使用Executors类提供给我们的静态工厂方法来更方便的创建一个线程池对象。创建了线程池对象后,我们就可以调用submit方法提交任务到线程池中去执行了;线程池使用完毕后我们要记得调用shutdown方法来关闭它。 for-each与常规for循环的效率对比 关于这个问题我们直接看《Effective Java》给我们做的解答: for-each能够让代码更加清晰,并且减少了出错的机会。 下面的惯用代码适用于集合与数组类型: for (Element e : elements) { doSomething(e); } 使用for-each循环与常规的for循环相比,并不存在性能损失,即使对数组进行迭代也是如此。实际上,在有些场合下它还能带来微小的性能提升,因为它只计算一次数组索引的上限。 简述Java IO与NIO的区别 Java IO是面向流的,这意味着我们需要每次从流中读取一个或多个字节,直到读取完所有字节;NIO是面向缓冲的,也就是说会把数据读取到一个缓冲区中,然后对缓冲区中的数据进行相应处理。 Java IO是阻塞IO,而NIO是非阻塞IO。 Java NIO中存在一个称为选择器(selector)的东西,它允许你把多个通道(channel)注册到一个选择器上,然后使用一个线程来监视这些通道:若这些通道里有某个准备好可以开始进行读或写操作了,则开始对相应的通道进行读写。而在等待某通道变为可读/写期间,请求对通道进行读写操作的线程可以去干别的事情。 反射的作用与原理 反射的作用概括地说是运行时获取类的各种定义信息,比如定义了哪些属性与方法。原理是通过类的class对象来获取它的各种信息。 Java中的泛型机制 关于泛型机制的详细介绍请直接戳 Java核心技术点之泛型 常见设计模式 所谓“设计模式”,不过是面向对象编程中一些常用的软件设计手法,并且经过实践的检验,这些设计手法在各自的场景下能解决一些需求,因此它们就成为了如今广为流传的”设计模式“。也就是说,正式因为在某些场景下产生了一些棘手的问题,才催生了相应的设计模式。明确了这一点,我们在学习某种设计模式时要充分理解它产生的背景以及它所解决的主要矛盾是什么。 常用的设计模式可以分为以下三大类: 创建型模式: 包括工厂模式(又可进一步分为简单工厂模式、工厂方法模式、抽象工厂模式)、建造者模式、单例模式。 结构型模式: 包括适配器模式、桥接模式、装饰模式、外观模式、享元模式、代理模式。 行为型模式: 包括命令模式、中介者模式、观察者模式、状态模式、策略模式。 注解的基本概念与使用 注解可以看作是“增强版的注释”,它可以向编译器、虚拟机说明一些事情。 注解是描述Java代码的代码,它能够被编译器解析,注解处理工具在运行时也能够解析注解。注解本身是“被动”的信息,只有主动解析它才有意义。 除了向编译器/虚拟机传递信息,我们也可以使用注解来生成一些“模板化”的代码。

优秀的个人博客,低调大师

程序员面试必备的20条Python经典面试

1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模式: 1. classSingleton(type): def __init__(cls, name, bases, dict): super(Singleton, cls).__init__(name, bases, dict) cls.instance = None def __call__(cls, *args, **kw): if cls.instance isNone: cls.instance = super(Singleton, cls).__call__(*args, **kw) return cls.instance classMyClass(object): __metaclass__ = Singleton print

优秀的个人博客,低调大师

面试必备:nginx知识梳理

前言 完整实例可用于参考学习使用。地址: http://github.crmeb.net/u/defu Nginx概念 Nginx 是一个高性能的 HTTP 和反向代理服务。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好。 Nginx 专为性能优化而开发,性能是其最重要的考量指标,实现上非常注重效率,能经受住高负载的考验,有报告表明能支持高达50000个并发连接数。 在连接高并发的情况下,Nginx 是 Apache 服务不错的替代品:Nginx 在美国是做虚拟主机生意的老板们经常选择的软件平台之一。 反向代理 在说反向代理之前,先来说说什么是代理和正向代理。 代理 代理其实就是一个中介,A和B本来可以直连,中间插入一个C,C就是中介。刚开始的时候,代理多数是帮助内网client(局域网)访问外网server用的。 后来出现了反向代理,反向这个词在这儿的意思其实是指方向相反,即代理将来自外网客户端的请求转发到内网服务器,从外到内。 正向代理 正向代理即是客户端代理,代理客户端,服务端不知道实际发起请求的客户端。 正向代理类似一个跳板机,代理访问外部资源。 比如我们国内访问谷歌,直接访问访问不到,我们可以通过一个正向代理服务器,请求发到代理服服务上,代理服务器能够访问谷歌,这样由代理去访问谷歌取到返回数据,再返回给我们,这样我们就能访问谷歌了。 反向代理 反向代理即是服务端代理,代理服务端,客户端不知道实际提供服务的服务端。 客户端是感知不到代理服务器的存在。 是指以代理服务器来接受 Internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 Internet 上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。 负载均衡 关于负载均衡,先来举个例子: 地铁大家应该都坐过吧,我们一般在早高峰乘地铁时候,总有那么一个地铁口人最拥挤,这时候,一般会有个地铁工作人员A拿个大喇叭在喊“着急的人员请走B口,B口人少车空”。而这个地铁工作人员A就是负责负载均衡的。 为了提升网站的各方面能力,我们一般会把多台机器组成一个集群对外提供服务。然而,我们的网站对外提供的访问入口都是一个的,比如www.taobao.com。那么当用户在浏览器输入www.taobao.com的时候如何将用户的请求分发到集群中不同的机器上呢,这就是负载均衡在做的事情。 负载均衡(Load Balance),意思是将负载(工作任务,访问请求)进行平衡、分摊到多个操作单元(服务器,组件)上进行执行。是解决高性能,单点故障(高可用),扩展性(水平伸缩)的终极解决方案。 Nginx提供的负载均衡主要有三种方式:轮询,加权轮询,Ip hash。 轮询 nginx默认就是轮询其权重都默认为1,服务器处理请求的顺序:ABCABCABCABC.... upstream mysvr { server 192.168.8.1:7070; server 192.168.8.2:7071; server 192.168.8.3:7072; } 复制代码 加权轮询 根据配置的权重的大小而分发给不同服务器不同数量的请求。如果不设置,则默认为1。下面服务器的请求顺序为:ABBCCCABBCCC.... upstream mysvr { server 192.168.8.1:7070 weight=1; server 192.168.8.2:7071 weight=2; server 192.168.8.3:7072 weight=3; } 复制代码 ip_hash iphash对客户端请求的ip进行hash操作,然后根据hash结果将同一个客户端ip的请求分发给同一台服务器进行处理,可以解决session不共享的问题。 upstream mysvr { server 192.168.8.1:7070; server 192.168.8.2:7071; server 192.168.8.3:7072; ip_hash; } 复制代码 动静分离 动态与静态页面区别 静态资源: 当用户多次访问这个资源,资源的源代码永远不会改变的资源(如:HTML,JavaScript,CSS,img等文件)。 动态资源:当用户多次访问这个资源,资源的源代码可能会发送改变(如:.jsp、servlet 等)。 什么是动静分离 动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路。 动静分离简单的概括是:动态文件与静态文件的分离。 为什么要用动静分离 为了加快网站的解析速度,可以把动态资源和静态资源用不同的服务器来解析,加快解析速度。降低单个服务器的压力。 Nginx安装 windows下安装 1、下载nginx nginx.org/en/download… 下载稳定版本。以nginx/Windows-1.20.1为例,直接下载 nginx-1.20.1.zip。 下载后解压,解压后如下: 2、启动nginx 直接双击nginx.exe,双击后一个黑色的弹窗一闪而过 打开cmd命令窗口,切换到nginx解压目录下,输入命令 nginx.exe ,回车即可 3、检查nginx是否启动成功 直接在浏览器地址栏输入网址 http://localhost:80 回车,出现以下页面说明启动成功! Docker安装nginx 我之前的文章也讲过Linux下安装的步骤,我采用的是docker安装的,很简单。 相关链接如下:Docker(三):Docker部署Nginx和Tomcat 1、查看所有本地的主机上的镜像,使用命令docker images 2、创建 nginx 容器 并启动容器,使用命令docker run -d --name nginx01 -p 3344:80 nginx 3、查看已启动的容器,使用命令docker ps 浏览器访问服务器ip:3344,如下,说明安装启动成功。 注意:如何连接不上,检查阿里云安全组是否开放端口,或者服务器防火墙是否开放端口! linux下安装 1、安装gcc 安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc 环境,则需要安装: yum install gcc-c++ 复制代码 2、PCRE pcre-devel 安装 PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正则表达式,所以需要在 linux 上安装 pcre 库,pcre-devel 是使用 pcre 开发的一个二次开发库。nginx也需要此库。命令: yum install -y pcre pcre-devel 复制代码 3、zlib 安装 zlib 库提供了很多种压缩和解压缩的方式, nginx 使用 zlib 对 http 包的内容进行 gzip ,所以需要在 Centos 上安装 zlib 库。 yum install -y zlib zlib-devel 复制代码 4、OpenSSL 安装 OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及 SSL 协议,并提供丰富的应用程序供测试或其它目的使用。 nginx 不仅支持 http 协议,还支持 https(即在ssl协议上传输http),所以需要在 Centos 安装 OpenSSL 库。 yum install -y openssl openssl-devel 复制代码 5、下载安装包 手动下载.tar.gz安装包,地址:nginx.org/en/download… 下载完毕上传到服务器上 /root 6、解压 tar -zxvf nginx-1.20.1.tar.gz cd nginx-1.20.1 复制代码 7、配置 使用默认配置,在nginx根目录下执行 ./configue make make install 复制代码 查找安装路径: whereis nginx 8、启动 nginx ./nginx 复制代码 启动成功,访问页面:ip:80 Nginx常用命令 注意:使用Nginx操作命令前提,必须进入到Nginx目录 /usr/local/nginx/sbin 1、查看Nginx版本号:./nginx -v 2、启动 Nginx:./nginx 3、停止 Nginx:./nginx -s stop 或者./nginx -s quit 4、重新加载配置文件:./nginx -s reload 5、查看nginx进程:ps -ef|grep nginx Nginx配置文件 Nginx配置文件的位置:/usr/local/nginx/conf/nginx.conf Nginx配置文件有3部分组成: 1、全局块 从配置文件开始到 events 块之间的内容,主要会设置一些影响 nginx 服务器整体运行的配置指令,比如:worker_processes 1。 这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是会受到硬件、软件等设备的制约。一般设置值和CPU核心数一致。 2、events块 events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,比如:worker_connections 1024 表示每个 work process 支持的最大连接数为 1024,这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。 3、http块 http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80;#监听端口 server_name localhost;#域名 location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } 复制代码 这算是 Nginx 服务器配置中最频繁的部分。 演示示例 反向代理/负载均衡 我们在windows下演示,首先我们创建两个springboot项目,端口是9001和9002,如下: 我们要做的就是将localhost:80代理localhost:9001和localhost:9002这两个服务,并且让轮询访问这两个服务。 nginx配置如下: worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream jiangwang { server 127.0.0.1:9001 weight=1;//轮询其权重都默认为1 server 127.0.0.1:9002 weight=1; } server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; proxy_pass http://jiangwang; } } } 复制代码 我们先将项目打成jar包,然后命令行启动项目,然后在浏览器上访问localhost来访问这两个项目,我也在项目中打印了日志,操作一下来看看结果,是不是两个项目轮询被访问。 可以看到,访问localhost,这两个项目轮询被访问。 接下来我们将权重改为如下设置: upstream jiangwang { server 127.0.0.1:9001 weight=1; server 127.0.0.1:9002 weight=3; } 复制代码 重新加载一个nginx的配置文件:nginx -s reload 加载完毕,我们再访问其localhost,观察其访问的比例: 结果显示,9002端口的访问次数与9001访问的次数基本上是3:1。 动静分离 1、将静态资源放入本地新建的文件里面,例如:在D盘新建一个文件data,然后再data文件夹里面在新建两个文件夹,一个img文件夹,存放图片;一个html文件夹,存放html文件;如下图: 2、在html文件夹里面新建一个a.html文件,内容如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Html文件</title> </head> <body> <p>Hello World</p> </body> </html> 复制代码 3、在img文件夹里面放入一张照片,如下: 4、配置nginx中nginx.conf文件: location /html/ { root D:/data/; index index.html index.htm; } location /img/ { root D:/data/; autoindex on;#表示列出当前文件夹中的所有内容 } 复制代码 5、启动nginx,访问其文件路径,在浏览器输入http://localhost/html/a.html,如下: 6、在浏览器输入http://localhost/img/ Nginx工作原理 mater&worker master接收信号后将任务分配给worker进行执行,worker可有多个。 worker如何工作 客户端发送一个请求到master后,worker获取任务的机制不是直接分配也不是轮询,而是一种争抢的机制,“抢”到任务后再执行任务,即选择目标服务器tomcat等,然后返回结果。 worker_connection 发送请求占用了woker两个或四个连接数。 普通的静态访问最大并发数是:worker_connections * worker_processes/ 2 ,若是 HTTP 作为反向代理来说,最大并发数量应该是 worker_connections * worker_processes/ 4 。当然了,worker数也不是越多越好,worker数和服务器的CPU数相等时最适宜的。 优点 可以使用 nginx –s reload 热部署,利用 nginx 进行热部署操作每个 woker 是独立的进程,若其中一个woker出现问题,其他继续进行争抢,实现请求过程,不会造成服务中断。 总结 关于 Nginx 的基本概念、安装教程、配置、使用实例以及工作原理,本文都做了详细阐述。希望本文对你有所帮助。 如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点star: http://github.crmeb.net/u/defu 不胜感激 !

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。