5.9 Limax Http


  • 5.9.4 HttpServer类

    • 1. HttpServer的create方法用来在一个主机端口上创建一个Http服务器,调用包含SSLContext参数的方法即可以创建一个Https服务器。对于应用而言,HttpExchange,WebSocketExchange上通过调用getSSLSession方法即可知道自己到底运行在http环境还是https环境。

    • 2. HttpServer的createHost方法使用一个域名创建虚拟主机,HttpServer本身就是默认虚拟主机,同一域名上第二次createHost等同于getHost。

    • 3. 虚拟主机的createContext方法在一个path上安装HttpHandler或者WebSocketHandler,removeContext移除path上对应的Handler。

    • 4. HttpServer的get,set方法用来存取HttpServer.Parameter定义的配置参数,配置参数非常多,类型也比较复杂,通常情况下默认参数应该够用了,如果修改可以参考源码。

    • 5. HttpServer的start,stop方法用于启停服务器,重复启停将导致UnsupportedOperationException异常。

    • 6. HttpServer的register方法可以注册一个Closeable,stop服务器的时候被调用。

    • 7. HttpServer的createFileSystemHandler方法用于创建一个静态文件服务器handler,效果基本等同于常见的静态文件服务器。参数比较多,htdocs指定文件服务器根目录;textCharset指定文本文件字符集;mmapThreshold指定使用文件映射的尺寸阈值,小于阈值的文件数据直接读到内存,否则使用文件映射;compressThreshold指定文件数据压缩阈值,压缩尺寸除以原始尺寸小于阈值的说明压缩有效使用压缩版本,否则使用非压缩版本,文件是否允许压缩由limax.http.ContentType枚举类型决定,通常来说文字内容允许压缩,图片不压缩;indexes数组指定缺省情况下默认的index文件,通常应该配置为index.html和index.htm;如果碰到目录访问,目录下不存在indexes指定的缺省文件的情况下,browseDir决定了是否允许浏览该目录,如果不允许以403FORBIDDEN响应;browseDirExceptions指定作为例外的那些目录。


  • 5.9.5 示例

    • 1. 源码目录下,demo/httpserver提供一个示例,可以根据具体环境适当调整。

    • 2. 如果要试验https,可以先安装根证书ca.p7b,然后在代码中给出localhost.p12的正确路径,运行服务器之后,浏览器通过https://localhost/访问即可。(也可以参考附录PKIX支持,建立自己的证书体系)

    • 3. 示例提供一个静态http服务器,可以试验创建静态网站。访问/upload.html和/upload2.html可以试验文件上传,了解FormData的特性。访问/websocket.html可以试验websocket。访问/sse.html可以试验Server-Sent Events。访问/exception可以试验handle抛出异常的情况。访问/async可以试验异步响应。

    • 4. 服务器支持从HTTP/1.1 upgrade到HTTP/2,但是当前似乎没有任何客户端支持这一能力。

    • 5. 如果要试验不加密的HTTP/2,只能搜索安装nghttp这样一个命令行程序,当前没有任何浏览器支持不加密的HTTP/2。

    • 6. 如果https配置完成,使用JDK8运行服务器,也不可能支持HTTP/2,因为JDK8的SSLEngine不支持ALPN。

    • 7. JDK8以上的JDK运行服务器,即可支持HTTP/2,但是当前的JDK11的SSLEngine存在bug,如果使用firefox访问,然后频繁刷新,SSL的握手方法就会陷入死循环。JDK13能够通过测试。


  • 5.9.6 高级话题

    • 服务器模型

      • 1. 服务器采用完全的异步模型(HTTP/2这样的协议一个连接上就能并发大量请求,如果一个请求对应一个线程执行服务,少量的用户连接就能耗费大量服务器线程),通过计算请求的hash值选择线程执行服务。服务handle在实现上尽量不要阻塞,如果存在数据库IO尽可能使用cache,重负荷情况下应该设置更大的服务线程池规模。

      • 2. 为了跟limax框架其它服务统一,使用Engine.open启动网络引擎。服务器参数NETSERVER_WORKMODE为true选择异步网络模型,false选择poll网络模型。

      • 3. Engine.open的参数nProcessors决定了网络线程池规模,网络线程池负责所有请求数据的解析,关闭消息的投递。参数protocolSchedulers配置的调度器仅被HTTP/2的定时器使用,只需要HTTP服务的情况下通常不需要配置太大。参数applicationExecutors决定了服务线程池规模,服务线程池用于handle请求,执行流控。


    • 数据发送

      • 1. HTTP/1.1,HTTP2均支持流控,FLOWCONTROL_WINDOW_SIZE配置了流控窗口大小。

      • 2. WebSocket上如果需要发送大量数据,需要根据event.type()==SENDREADY决定后续发送确保正确的流控,防止数据堆积,交互式应用通常不必严格进行流控。

      • 3. Server-Sent Events同WebSocket类似,使用onSendReady实现流控。

      • 4. CONGESTION_TIMEOUT时限内发送缓冲区没有任何消耗,被看成是严重拥塞,连接随即关闭。


    • 数据上传

      • 1. HTTP协议通过POST方法执行上传,但是POST本身的设计过于简单,实际应用中如果不小心处理POST,恶意客户端很容易利用POST消耗服务器资源。最大的问题在于POST的数据尺寸。

      • 2. 不涉及文件上传的POST,通常用来发送一些尺寸较大的查询,这种情况约定最大尺寸,使用FormData的postLimit方法简单限制即可。

      • 3. 涉及文件上传的POST就要复杂得多了,文件可能几K,几M,几G都有可能,也可能一次上传多个文件,postLimit很难确定。(为了避免过大的内存开销,FormData的useTempFile方法对于通常的文件上传还是必要的)

      • 4. 示例中的/upload2.html,第一个输入框应该填写一个估计的上传尺寸(上传文件大小加上浏览器添加的MIME头信息的大小)尺寸过小则上传失败。

      • 5. 实际应用中,应该在具体文件上传之前,协商上传细节,例如文件数量,文件大小,从而估算总尺寸。协商结果在协商服务与上传服务间共享,客户端交换协商结果的时效性key,保证上传服务根据协商结果正确配置。

      • 6. HttpHandler的censor(HttpExchange exchange)方法由网络线程执行,只要抛出异常就可以结束连接。如果必要,可以在其中完成更多的FormData审查(FormData可以获取已经传完的部分信息)。FormData也提供了getBytesCount(),getCreateTime()这样的方法,可以用来完成上传速率管理一类的任务,例如,直接关闭速率过慢的连接。(如果上传停顿,HTTP11_REQUEST_TIMEOUT,HTTP2_IDLE_TIMEOUT这一类的配置参数会起作用)


上一页 下一页