满足高并发性时的简单Web服务器

这不是作业,而是我在网上找到的面试问题。

java代码是:

public class SimpleWebServer{ public static void handleRequest(Socket c) { //Process the request } public static void main(String[] args) throws IOException { ServerSocket server=new ServerSocket(80); while(true) { final Socket connection=server.accept(); Runnable task=new Runnable(){ @Override public void run() { handleRequest(connection); } }; new Thread(task).start(); } } } 

问题是当并发性很高时会出现什么样的潜在问题? 我的分析是:

  1. 它没有使用synchronized关键字,因此可能会出现竞争条件。
  2. 它应该使用更高效的线程池。
  3. 对于每个传入的线程,类似乎总是创建一个新的ServerSocket,当高并发发生时会占用大量空间?

我看到的主要问题是你已经确定的问题。 每个请求线程模型本质上存在缺陷(通过在Apache上广泛采用Nginx和lighttpdcertificate)。 迁移到ExecutorService(可能由线程池支持)将是一个不错的选择。

通过从每个请求的线程更改为简单的任务提交到ExecutorService,您将此应用程序转移到基于事件的模型。 Web上有很多材料宣扬基于事件的基于线程的模型的可伸缩性优点。

handleRequest方法上使用’synchronized’是一种非常powershell的策略,并且根据方法的特定内容,更优选的是更精细的锁定策略(或无锁逻辑)。 您提到的ServerSocket创建只对应用程序发生一次,因此这不是一个可扩展性问题。 accept方法为每个连接创建一个新的Socket实例,但这些实例很便宜。 查看JDK 6源代码,包括分配7个布尔值,一个锁定Object ,以及检查一些内部状态 – 即,可能不会成为问题。

基本上,你走在正确的轨道上! 希望这可以帮助。

以下列出了潜在的问题

1)产生一个线程占用CPU周期,每个线程都有自己的数据结构,消耗内存。 当一个线程阻塞时,JVM保存其状态并选择另一个线程运行,并恢复所选线程的状态,称为上下文切换 。 随着线程数量的增加,线程消耗的资源也越来越多。 引入Threadpool是为了通过限制线程数和重用线程而不是生成新线程来解决这个问题。

2)最令人沮丧和重要的问题是使这些线程以同步方式共享或访问变量(例如状态)。 很容易使这些变量不一致。 因此,一些程序员更喜欢使用单线程环境(例如NIO)而不是multithreading环境。

3)当你想追查问题时,没有日志记录系统会使线程环境更加难以调试。

4)每次要接受新客户端时都不需要实例化新的serversocket(),因为它是一个共享的Serversocket实例。