欢迎拜访我的GitHub
这儿分类和汇总了欣宸的全部原创(含配套源码):github.com/zq2599/blog…
本篇概览
- 今日我们以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(重定向)等
- 除了官方模块,还有许多强大第三方模块能够挑选,如下图,更多概况参阅:www.nginx.com/resources/w…
- 大名鼎鼎的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扩展nginx
- nginx-clojure的作用很好了解:OpenResty支撑用Lua扩展nginx,nginx-clojure支撑用Java扩展nginx
关于nginx-clojure
- nginx-clojure是个第三方Nginx模块,官方的介绍是Nginx module for embedding Clojure / Java / Groovy programs, typically those Ring based handlers
- nginx-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.github.io
实战功用介绍
- 虽然nginx-clojure支撑许多功用,但是篇幅所限,因而本篇以了解为主,还是经典的Hello world,更多精彩内容留给后续的系列文章
- 今日的实战效果如下图,我们编写HelloHandler.java并在nginx做好装备,然后用浏览器建议恳求后,HelloHandler的代码就会被履行,浏览器会收到HelloHandler回来的内容,这就证实了java代码能够在nginx上运转:
- 为了完结上述功用,接下来的操作步骤如下图:
- 感谢您听我唠叨了这么久,接下来,实战初步
环境信息
- 这儿给出我的实战环境信息供您参阅,这个环境能够正常运转所有实战:
- 操作系统:macOS Big Sur 11.5.2 (20G95)
- JDK:1.8.0_281
- Maven:3.8.1
下载集成了nginx-clojure模块的nginx包
- 我们要做的榜首件事是下载一个特别的nginx,之所以说它特别,是由于它已集成了nginx-clojure模块,开箱即用
- 下载地址:sourceforge.net/projects/ng… ,如下图红框,我这儿挑选的是最新的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:
./nginx -v
nginx version: nginx/1.18.0
编码,开发java版handler
- 接下来初步写代码,先新建一个maven工程(我这儿名叫simple-hello),pom.xml中需要装备repository节点,以及唯一的依靠nginx-clojure,如下所示:
<repositories>
<repository>
<id>clojars.org</id>
<url>http://clojars.org/repo</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内容:
package 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类:
location /java {
content_handler_type 'java';
content_handler_name 'com.bolingcavalry.simplehello.HelloHandler';
}
- 修改后,完好的nginx.conf内容如下,可见有许多java相关的装备,在本篇我们都保持不动,留下后面的文章解锁:
###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 http://nginx-clojure.github.io/directives.html#jvm_classpath
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检查问题,例如我这儿遇到过端口占用导致发动失利:
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: 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验证服务是否正常,恳求地址是http://127.0.0.1:8080/java
- 呼应如下图所示,契合预期,回来的便是我们定制的HelloHandler的内容
- 至此,nginx-clojure的入门操作就完结了,虽然寥寥几行代码,但却给java程序员翻开了一扇窗:用我们了解的技能去扩展nginx,打造更契合事务的web服务器,以最短链路完结web呼应
- 本篇仅仅nginx-clojure之旅的初步,先对nginx-clojure有个明晰的认识,接下来的文章我们会深度探索它,让它更好的服务于事务
源码下载
- 本篇的完好源码可在GitHub下载到,地址和链接信息如下表所示(github.com/zq2599/blog…
称号 | 链接 | 备注 |
---|---|---|
项目主页 | github.com/zq2599/blog… | 该项目在GitHub上的主页 |
git库房地址(https) | github.com/zq2599/blog… | 该项目源码的库房地址,https协议 |
git库房地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的库房地址,ssh协议 |
- 这个git项目中有多个文件夹,本篇的源码在nginx-clojure-tutorials文件夹下,如下图红框所示:
欢迎重视:程序员欣宸
学习路上,你不孑立,欣宸原创一路相伴…