龙空技术网

精选版:用Java扩展Nginx(nginx-clojure 入门)

程序员欣宸 862

前言:

而今姐妹们对“nginx配置返回文件下载”大约比较关心,朋友们都想要了解一些“nginx配置返回文件下载”的相关内容。那么小编同时在网摘上收集了一些有关“nginx配置返回文件下载””的相关内容,希望看官们能喜欢,姐妹们一起来学习一下吧!

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):

本篇概览今天咱们以Java程序员的视角,来聊聊如何用Java来扩展Nginx的能力,全文由以下内容组成:什么是Nginx什么是Nginx扩展扩展Nginx,意义何在?想用Java扩展Nginx会有问题吗?主角登场:nginx-clojure模块,让Java扩展Nginx成为显示总的来说这是一篇从概念到实践的入门文章,接下来,一起开始愉快的nginx-clojure之旅吧!关于Nginx以欣宸自己为例,nginx对java程序员来说并不陌生,下图应该是最常见的使用场景了:反向代理关于Nginx扩展除了反向代理,nginx的模块化机制让nginx具备了更多丰富的特性,例如ngx_http_log_module(日志)、ngx_http_rewrite_module(重定向)等除了官方模块,还有很多强大第三方模块可以选择,如下图,更多详情参考:大名鼎鼎的OpenResty就是基于 Nginx 扩展的,用Lua做二次开发web功能,得到了广泛的应用如此看来,在nginx上做二次开发并非神秘高深莫测,我们也可以按照自己的需要去定制和扩展nginx的功能作为一名Java程序员,自然就想到了:可以用Java去扩展Nginx的能力吗?为什么要用java对nginx扩展?把java代码写在nginx上,让nginx与业务耦合的可能性变大,经验丰富的您一定会发现这是个危险的趋势,毕竟nginx已经接近后台服务的最外层了,稳定是首要考虑的,正常情况下,下图这种用法才是生产环境的常见fang方案:将nginx作为反向代理,业务功能独立部署这么看来,在nginx上写java代码是否合适呢?欣宸给不出权威答案,但是可以从大神的作品中得到启示开涛大神的《跟我学Nginx+Lua开发》讲述了如何用OpenResty在Nginx上用Lua进行开发,适用于web应用、接入网关、Web防火墙、缓存服务器等场景下,并且在实体书《亿级流量网站架构核心技术》也有详细说明,例如京东商品详情页,就是在nginx上读取缓存直接返回的综上所述,欣宸不会因为学习了这个技术,就把业务逻辑全部在nginx上实现,但是在缓存、鉴权等场景,可以考虑用熟悉的java在nginx上实现Java程序员的尴尬定制Nginx,打造高性能Web服务,带着这个美好憧憬,我打开了有关模块开发的Nginx官方资料然后,画风开始剧变,而且是朝着我不想面对的方向,如下图模块开发用的居然是C语言!然而,欣宸只是个精通CRUD的Java程序员啊这可怎么办?随手打开一个网页就让梦想破灭?nginx-clojure,让Java扩展nginx成为现实经过一番搜索,终于找到了nginx-clojure模块,如下图,是它让java扩展nginx成为现实nginx-clojure的作用很好理解:OpenResty支持用Lua扩展nginx,nginx-clojure支持用Java扩展nginxnginx-clojure的作用很好理解:OpenResty支持用Lua扩展nginx,nginx-clojure支持用Java扩展nginx关于nginx-clojurenginx-clojure是个第三方Nginx模块,官方的介绍是Nginx module for embedding Clojure / Java / Groovy programs, typically those Ring based handlersnginx-clojure模块支持嵌入式Clojure(闭包)、Java、Groovy等基于Ring的处理器(handler),那什么是Ring呢?Ring 在 Clojure 中是一个构建 Web 应用的底层接口和库. 它和 Ruby 的 Rack, Python 里面的WSGI 或者 Java Servlet 规范相似从java开发者角度来看,就是开发NginxJavaRingHandler的实现类,然后该类可以在nginx-clojure模块中被运行nginx-clojure的最新版本是v0.5.2,官网地址是:实战功能介绍尽管nginx-clojure支持很多功能,但是篇幅所限,因此本篇以了解为主,还是经典的Hello world,更多精彩内容留给后续的系列文章今天的实战效果如下图,咱们编写HelloHandler.java并在nginx做好配置,然后用浏览器发起请求后,HelloHandler的代码就会被执行,浏览器会收到HelloHandler返回的内容,这就证实了java代码可以在nginx上运行:为了实现上述功能,接下来的操作步骤如下图:感谢您听我唠叨了这么久,接下来,实战开始环境信息这里给出我的实战环境信息供您参考,这个环境可以正常运行所有实战:操作系统:macOS Big Sur 11.5.2 (20G95)JDK:1.8.0_281Maven:3.8.1下载集成了nginx-clojure模块的nginx包咱们要做的第一件事是下载一个特别的nginx,之所以说它特别,是因为它已集成了nginx-clojure模块,开箱即用下载地址: ,如下图红框,我这里选择的是最新的0.5.2版本:解压nginx包下载完毕后,解压,得到名为nginx-clojure-0.5.2的文件夹,里面的内容如下接下来根据您的操作系统对可执行文件做重命名,我这边是macOS,所以把nginx-macosx重命名为nginx,如果是linux,把nginx-linux-64重命名为nginx,如果是windows,就把nginx-win64.exe重命名为nginx.exe上述重命名操作是nginx-clojure官方推荐的,统一可执行文件名,这样运行文档中的命令就统一了执行命令./nginx -v,控制台响应如下,可见nginx版本是1.18.0:

shell./nginx -vnginx version: nginx/1.18.0
编码,开发java版handler接下来开始写代码,先新建一个maven工程(我这里名叫simple-hello),pom.xml中需要配置repository节点,以及唯一的依赖nginx-clojure,如下所示:
xml<repositories>  <repository>    <id>clojars.org</id>    <url>;/url>    </repository></repositories><dependencies>  <dependency>    <groupId>nginx-clojure</groupId>    <artifactId>nginx-clojure</artifactId>    <version>0.5.2</version>  </dependency></dependencies>
然后新增文件HelloHandler.java,如下所示,代码非常简单,实现NginxJavaRingHandler接口,invoke方法返回的数组中只有三个元素:返回码、响应header的键值对集合、响应body内容:
javapackage com.bolingcavalry.simplehello;import nginx.clojure.java.ArrayMap;import nginx.clojure.java.NginxJavaRingHandler;import java.time.LocalDateTime;import java.util.Map;import static nginx.clojure.MiniConstants.CONTENT_TYPE;import static nginx.clojure.MiniConstants.NGX_HTTP_OK;/** * @author zq2599@gmail.com * @Title: 产生内容的handler * @Package * @Description: * @date 2/1/22 12:41 PM */public class HelloHandler implements NginxJavaRingHandler {    @Override    public Object[] invoke(Map<String, Object> request) {        return new Object[] {                NGX_HTTP_OK, //http status 200                ArrayMap.create(CONTENT_TYPE, "text/plain"), //headers map                "Hello, Nginx clojure! " + LocalDateTime.now()  //response body can be string, File or Array/Collection of them        };    }}
至此,编码完成,欣宸精通Hello World果然并非空穴来风…编译,生成jar在pom.xml所在目录执行编译构建的命令mvn clean package -U,会在target目录下生成jar包,只有3K大小:jar放入nginx的jars目录将前面生成的simple-hello-1.0-SNAPSHOT.jar文件放入下图红框的jars文件夹内修改nginx的配置打开nginx-clojure-0.5.2/conf/nginx.conf文件,在server配置中增加一个location配置,内容如下,指定了handler类型,以及对应的java类:
javalocation /java {         content_handler_type 'java';         content_handler_name 'com.bolingcavalry.simplehello.HelloHandler';}
修改后,完整的nginx.conf内容如下,可见有很多java相关的配置,在本篇咱们都保持不动,留待后面的文章解锁:
shell###you can uncomment next two lines for easy debug###Warning: if master_process is off, there will be only one nginx worker running. Only use it for debug propose.#daemon  off;#master_process  off;#user  nobody;worker_processes  1;#error_log  logs/error.log;#error_log  logs/error.log  notice;#error_log  logs/error.log  info;#pid        logs/nginx.pid;events {    worker_connections  1024;}http {    include       mime.types;    default_type  application/octet-stream;    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '    #                  '$status $body_bytes_sent "$http_referer" '    #                  '"$http_user_agent" "$http_x_forwarded_for"';    #access_log  logs/access.log  main;    sendfile        on;    #tcp_nopush     on;    #keepalive_timeout  0;    keepalive_timeout  65;    #gzip  on;        jvm_path auto;        ### Set my app jars and resources, it must include nginx-clojure runtime jar,e.g. nginx-clojure-0.5.1.jar and     ### for clojure user clojure runtime jar is also needed.    ### See     jvm_classpath "libs/*:jars/*";        ###jvm heap memory    #jvm_options "-Xms1024m";    #jvm_options "-Xmx1024m";        #for enable java remote debug uncomment next two lines    #jvm_options "-Xdebug";    #jvm_options "-Xrunjdwp:server=y,transport=dt_socket,address=840#{pno},suspend=n";    ###threads number for request handler thread pool on jvm, default is 0.     ###check more details from     #jvm_workers 8;    server {        listen       8080;        server_name  localhost;        #charset koi8-r;        #access_log  logs/host.access.log  main;        location / {            root   html;            index  index.html index.htm;        }        #error_page  404              /404.html;        # redirect server error pages to the static page /50x.html        #        error_page   500 502 503 504  /50x.html;        location = /50x.html {            root   html;        }       location /clojure {          handler_type 'clojure';          handler_code ' 						(fn[req]						  {						    :status 200,						    :headers {"content-type" "text/plain"},						    :body  "Hello Clojure & Nginx!" 						    })          ';       }       location /java {         content_handler_type 'java';         content_handler_name 'com.bolingcavalry.simplehello.HelloHandler';       }       #      location /groovy {#          handler_type 'groovy';#          handler_code ' #               import nginx.clojure.java.NginxJavaRingHandler;#               import java.util.Map;#               public class HelloGroovy implements NginxJavaRingHandler {#                  public Object[] invoke(Map<String, Object> request){#                     return [200, //http status 200#                             ["Content-Type":"text/html"], //headers map#                             "Hello, Groovy & Nginx!"]; //response body can be string, File or Array/Collection of them#                  }#               }#          ';#       }#             }}
启动nginx启动命令很简单,在nginx-clojure-0.5.2目录下执行./nginx如果启动失败了,请打开nginx-clojure-0.5.2/logs/error.log查看问题,例如我这里遇到过端口占用导致启动失败:
shell2022/02/02 17:45:07 [emerg] 27703#0: bind() to 0.0.0.0:8080 failed (48: Address already in use)2022/02/02 17:45:07 [emerg] 27703#0: bind() to 0.0.0.0:8080 failed (48: Address already in use)2022/02/02 17:45:07 [emerg] 27703#0: bind() to 0.0.0.0:8080 failed (48: Address already in use)2022/02/02 17:45:07 [emerg] 27703#0: bind() to 0.0.0.0:8080 failed (48: Address already in use)2022/02/02 17:45:07 [emerg] 27703#0: bind() to 0.0.0.0:8080 failed (48: Address already in use)2022/02/02 17:45:07 [emerg] 27703#0: still could not bind()
验证打开postman验证服务是否正常,请求地址是响应如下图所示,符合预期,返回的就是咱们定制的HelloHandler的内容至此,nginx-clojure的入门操作就完成了,虽然寥寥几行代码,但却给java程序员打开了一扇窗:用咱们熟悉的技术去扩展nginx,打造更符合业务的web服务器,以最短链路完成web响应本篇只是nginx-clojure之旅的开端,先对nginx-clojure有个清晰的认识,接下来的文章咱们会深度探索它,让它更好的服务于业务源码下载本篇的完整源码可在GitHub下载到,地址和链接信息如下表所示():

名称

链接

备注

项目主页

该项目在GitHub上的主页

git仓库地址(https)

该项目源码的仓库地址,https协议

git仓库地址(ssh)

git@github.com:zq2599/blog_demos.git

该项目源码的仓库地址,ssh协议

这个git项目中有多个文件夹,本篇的源码在nginx-clojure-tutorials文件夹下,如下图红框所示:欢迎关注头条号:程序员欣宸学习路上,你不孤单,欣宸原创一路相伴...

标签: #nginx配置返回文件下载