前言
最近看到了国内开源的一个名为OpenNJet的项目,有一个响亮的口号:“下一代云原生应用引擎”。
一下子就被吸引到了。
先看下官方对OpenNJet的介绍:
OpenNJet 应用引擎是基于 NGINX 的面向互联网和云原生应用提供的运行时组态服务程序,作为底层引擎,OpenNJet 实现了NGINX 云原生功能增强、安全加固和代码重构,利用动态加载机制可以实现不同的产品形态,如Web服务器、流媒体服务器、负载均衡、代理(Proxy)、应用中间件、API网关、消息队列等产品形态等等。
OpenNJet 在云原生架构中作为数据平面,除了提供南北向通信网关的功能以外,还提供了服务网格中东西向通信能力。在原有功能基础上增加了透明流量劫持、熔断、遥测与故障注入等新功能特性。
看完这段介绍大概了解到了,这个OpenNjet应用引擎是基于NGINX开发的。经过我的对比分析,确实是这样子的,如果你用过NGINX,亲自编译过NGINX你会发现OpenNJet的编译选项和NGINX的都是很像的。源代码也是类似,所以对于接触过NGINX的同学来说上手OpenNJet是很容易的。
官方给了你选择OpenNJet的理由:
因为我算是稍微深度使用过NGINX的用户,我用NGINX做过线上的代理服务,部署过web服务,在流媒体领域还做过RTMP服务,还做过静态资源库。
我是对OpenNJet的动态配置这个模块很感兴趣的,首先说一下我使用Nginx时遇到的缺陷:Nginx确实是存在你如果想修改了配置,必须要重启服务,这也是领人头疼的,一旦运行起来,如果重新启动一下,会造成很多额外的损失。
因为我是做流媒体领域的。所以也想体验一下,OpenNjet如何接入流媒体服务。
所以本文会针对动态配置和流媒体服务两点做一些探索和研究。
Ubuntu通过deb包安装
这种方式就是拿来即用。使用是没有问题的,当然了如果你要做个测试或者当做一个服务去使用的话,完全没有问题。但是你想进行二次开发的话,这个方式就行不通了,需要自己从头到尾编译一遍。
先看一个比较简单的安装方法:
1、下载deb安装包:
https://gitee.com/njet-rd/njet/releases
2、下载好的:
zhenghui@zh-pc:build_njet$ ls -l njet_2.0.1-1~ubuntu.18.04~bionic_amd64.deb
-rwxrwxrwx 1 root root 19230036 4月 24 23:31 njet_2.0.1-1~ubuntu.18.04~bionic_amd64.deb
zhenghui@zh-pc:build_njet$
3、使用dpkg进行安装
zhenghui@zh-pc:build_njet$ sudo dpkg -i njet_2.0.1-1~ubuntu.18.04~bionic_amd64.deb
[sudo] zhenghui 的密码:
正在选中未选择的软件包 njet。
(正在读取数据库 ... 系统当前共安装有 706429 个文件和目录。)
准备解压 njet_2.0.1-1~ubuntu.18.04~bionic_amd64.deb ...
正在解压 njet (2.0.1) ...
正在设置 njet (2.0.1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/njet.service → /lib/systemd/system/njet.service.
正在处理用于 libc-bin (2.35-0ubuntu3.7) 的触发器 ...
zhenghui@zh-pc:build_njet$
看着一句:Created symlink /etc/systemd/system/multi-user.target.wants/njet.service → /lib/systemd/system/njet.service
说明已经在系统中创建了service的方式。
安装位置:
zhenghui@zh-pc:njet$ pwd
/usr/local/njet
zhenghui@zh-pc:njet$
zhenghui@zh-pc:njet$ ls
client_body_temp conf data fastcgi_temp html lib logs lualib modules proxy_temp sbin scgi_temp uwsgi_temp
zhenghui@zh-pc:njet$
功能体验
1、如何控制njet服务
njet做到了系统的services里,可以使用systemctl命令来控制服务,这一点对于使用者来说很方便。
然后就可以启动njet服务和关闭njet服务了:
systemctl start njet #启动服务
systemctl stop njet #停止服务
查看是否启动成功
zhenghui@zh-pc:soft$ sudo netstat -ntpl |grep njet
tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN 580250/njet: copilo
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 580233/njet: master
zhenghui@zh-pc:soft$
浏览器输入:http://127.0.0.1:8080/
出现如下界面既成功:
停止服务:
zhenghui@zh-pc:build_njet$ sudo systemctl stop njet
zhenghui@zh-pc:build_njet$
zhenghui@zh-pc:build_njet$ sudo netstat -ntpl |grep njet
zhenghui@zh-pc:build_njet$
还提供了其他的一些指令:
1、显示帮助信息 : njet -h
2、 启动:njet -p /tmpr/njet/ -c conf/njet.conf
常见启动参数:
- -p 指定prefix配置文件路径,不指定,默认/etc/njet
- -c 指定配置文件,不指定,默认njet.conf
- -e 指定error 日志文件
3、测试配置信息是否有错误: njet -t
4、显示版本:njet -v
5、显示编译阶段的参数: njet -V
6、快速停止:njet -s stop 或者 kill -TERM {进程id}
7、优雅停止服务:njet -s quit 或者 kill -QUIT {进程id}
8、重新加载配置:njet -s reload 或者 kill -HUP {进程id}
2、如何部署自己的web网站
我的安装目录在:/usr/local/njet
/usr/local/njet/html就是网站的默认root根目录。
root根目录的位置也是可以修改的:
vim /usr/local/njet/conf/njet.conf
1 worker_processes auto;
2
3 cluster_name njet;
4 node_name node1;
5
6 error_log logs/error.log error;
7
8 helper ctrl /usr/local/njet/modules/njt_helper_ctrl_module.so /usr/local/njet/conf/njet_ctrl.conf;
9 helper broker /usr/local/njet/modules/njt_helper_broker_module.so;
10
11 load_module /usr/local/njet/modules/njt_http_split_clients_2_module.so;
12 load_module /usr/local/njet/modules/njt_agent_dynlog_module.so;
13 load_module /usr/local/njet/modules/njt_http_dyn_bwlist_module.so;
14 load_module /usr/local/njet/modules/njt_dyn_ssl_module.so;
15 load_module /usr/local/njet/modules/njt_http_vtsc_module.so;
16 load_module /usr/local/njet/modules/njt_http_location_module.so;
17 #load_module /usr/local/njet/modules/njt_http_lua_module.so;
18 #load_module /usr/local/njet/modules/njt_http_modsecurity_module.so;
19 #load_module /usr/local/njet/modules/njt_http_dyn_modsecurity_module.so;
20
21
22 events {
23 worker_connections 1024;
24 }
25
26
27 http {
28 include mime.types;
29 access_log off;
30 vhost_traffic_status_zone;
31 #lua_package_path "$prefix/lualib/lib/?.lua;/usr/local/njet/modules/?.lua;;";
32 #lua_package_cpath "$prefix/lualib/clib/?.so;;";
33 server {
34 #modsecurity on;
35 #modsecurity_rules_file /usr/local/njet/conf/modsec/main.conf;
36
37 listen 8080;
38 location / {
39 root html;
40 }
41 }
42
43 }
还可以看到默认端口是listen = 8080
第一步:可以找到自己的web资源,放到你的安装目录下的html中
例如我放了一个admin的目录:
zhenghui@zh-pc:njet$ cd html/
zhenghui@zh-pc:html$ ls
50x.html 50x.html.dpkg-new 50x.html.dpkg-tmp admin index.html index.html.dpkg-new index.html.dpkg-tmp
zhenghui@zh-pc:html$ pwd
/usr/local/njet/html
zhenghui@zh-pc:html$
此时自己的网站就部署成功了
就这么简单,只需要一步。
3、使用API接口管理配置
njet提供了API接口来动态操作这一切,例如启动成功后,如果你什么都没改,会有一个8081的端口,可以访问:http://127.0.0.1:8081/doc/swagger/ 进入 swagger的api文档。
4、使用GUI管理配置
还提供了gui来控制
访问:
http://127.0.0.1:8081/doc/gui/
5、http_log模块动态配置
我们使用最简单的方式:http://127.0.0.1:8081/doc/gui/
打开web后,点开http_log模块:
此时accessLogOn为false,说明当前没有开启日志。可以看到当前logs目录下的文件状态
我们选择为true:
此时还没保存,可以看到logs的状态
我们修改一下,然后保存:
可以看到njet并没有重启,我们还在一直操作。
可以使用tail -f实时监控日志,看看日志是不是真的生效了:
此时可以刷新下web界面,可以看到日志哗啦啦的就出来了。
这就是动态配置的作用,不必重启。
编译安装
如果你是ubuntu需要安装如下:
sudo apt-get install gcc g++ make cmake libpcre2-dev libpcre3-dev libssl-dev zlib1g-dev perl m4 libtool automake autoconf vim-common unzip libcap2-bin
1、下载地址:
国内推荐从gitee上下载:https://gitee.com/njet-rd
国外推荐从github上下载:https://github.com/OpenNJet/OpenNJet
当然了,如果你会魔法的话,也建议直接从github上。
我下载的是目前最新版2.1.0:
root@zhenghui-tx:~/soft/build_OpenNJet# ls -l njet-v2.1.0.tar.gz
-rw-r--r-- 1 root root 29065901 Apr 24 09:13 njet-v2.1.0.tar.gz
root@zhenghui-tx:~/soft/build_OpenNJet#
解压:
root@zhenghui-tx:~/soft/build_OpenNJet#
root@zhenghui-tx:~/soft/build_OpenNJet# tar -zxvf njet-v2.1.0.tar.gz
解压后:
root@zhenghui-tx:~/soft/build_OpenNJet# cd njet-v2.1.0/
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# ls
auto build_cc.sh build_lua.sh CHANGES.ru configure doc Dockerfile.ubuntu img luajit man modules_dynamic njet_sidecar.conf README repos src
build build_k8s.sh CHANGES conf contrib Dockerfile html LICENSE lualib modules modules_static NOTICE README.md scripts
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
初次拿到一个陌生的需要编译的项目,肯定是先查看README.xx文档,然后就是看编译配置脚本:
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# ./configure --help
--help print this message
--prefix=PATH set installation prefix
--sbin-path=PATH set njet binary pathname
--modules-path=PATH set modules path
--conf-path=PATH set njet.conf pathname
--error-log-path=PATH set error log pathname
--pid-path=PATH set njet.pid pathname
--lock-path=PATH set njet.lock pathname
--user=USER set non-privileged user for
worker processes
--group=GROUP set non-privileged group for
worker processes
--build=NAME set build name
--builddir=DIR set build directory
--with-select_module enable select module
--without-select_module disable select module
--with-poll_module enable poll module
--without-poll_module disable poll module
--with-threads enable thread pool support
--with-file-aio enable file AIO support
--without-quic_bpf_module disable njt_quic_bpf_module
--without-dynamic-pool disable njet dynamic pool usage
--with-http_ssl_module enable njt_http_ssl_module
--with-http_v2_module enable njt_http_v2_module
--with-http_v3_module enable njt_http_v3_module
--with-http_realip_module enable njt_http_realip_module
--with-http_addition_module enable njt_http_addition_module
--with-http_xslt_module enable njt_http_xslt_module
--with-http_xslt_module=dynamic enable dynamic njt_http_xslt_module
--with-http_image_filter_module enable njt_http_image_filter_module
--with-http_image_filter_module=dynamic
enable dynamic njt_http_image_filter_module
--with-http_geoip_module enable njt_http_geoip_module
--with-http_geoip_module=dynamic enable dynamic njt_http_geoip_module
--with-http_sub_module enable njt_http_sub_module
--with-http_dav_module enable njt_http_dav_module
--with-http_flv_module enable njt_http_flv_module
--with-http_mp4_module enable njt_http_mp4_module
--with-http_gunzip_module enable njt_http_gunzip_module
--with-http_gzip_static_module enable njt_http_gzip_static_module
--with-http_auth_request_module enable njt_http_auth_request_module
--with-http_random_index_module enable njt_http_random_index_module
--with-http_secure_link_module enable njt_http_secure_link_module
--with-http_degradation_module enable njt_http_degradation_module
--with-http_slice_module enable njt_http_slice_module
--with-http_stub_status_module enable njt_http_stub_status_module
--without-http_charset_module disable njt_http_charset_module
--without-http_gzip_module disable njt_http_gzip_module
--without-http_ssi_module disable njt_http_ssi_module
--without-http_userid_module disable njt_http_userid_module
--without-http_access_module disable njt_http_access_module
--without-http_auth_basic_module disable njt_http_auth_basic_module
--without-http_mirror_module disable njt_http_mirror_module
--without-http_autoindex_module disable njt_http_autoindex_module
--without-http_geo_module disable njt_http_geo_module
--without-http_map_module disable njt_http_map_module
--without-http_split_clients_module disable njt_http_split_clients_module
--without-http_referer_module disable njt_http_referer_module
--without-http_rewrite_module disable njt_http_rewrite_module
--without-http_proxy_module disable njt_http_proxy_module
--without-http_fastcgi_module disable njt_http_fastcgi_module
--without-http_uwsgi_module disable njt_http_uwsgi_module
--without-http_scgi_module disable njt_http_scgi_module
--without-http_grpc_module disable njt_http_grpc_module
--without-http_memcached_module disable njt_http_memcached_module
--without-http_limit_conn_module disable njt_http_limit_conn_module
--without-http_limit_req_module disable njt_http_limit_req_module
--without-http_empty_gif_module disable njt_http_empty_gif_module
--without-http_browser_module disable njt_http_browser_module
--without-http_upstream_hash_module
disable njt_http_upstream_hash_module
--without-http_upstream_ip_hash_module
disable njt_http_upstream_ip_hash_module
--without-http_upstream_least_conn_module
disable njt_http_upstream_least_conn_module
--without-http_upstream_random_module
disable njt_http_upstream_random_module
--without-http_upstream_keepalive_module
disable njt_http_upstream_keepalive_module
--without-http_upstream_zone_module
disable njt_http_upstream_zone_module
--with-http_perl_module enable njt_http_perl_module
--with-http_perl_module=dynamic enable dynamic njt_http_perl_module
--with-perl_modules_path=PATH set Perl modules path
--with-perl=PATH set perl binary pathname
--http-log-path=PATH set http access log pathname
--http-client-body-temp-path=PATH set path to store
http client request body temporary files
--http-proxy-temp-path=PATH set path to store
http proxy temporary files
--http-fastcgi-temp-path=PATH set path to store
http fastcgi temporary files
--http-uwsgi-temp-path=PATH set path to store
http uwsgi temporary files
--http-scgi-temp-path=PATH set path to store
http scgi temporary files
--without-http disable HTTP server
--without-http-cache disable HTTP cache
--with-mail enable POP3/IMAP4/SMTP proxy module
--with-mail=dynamic enable dynamic POP3/IMAP4/SMTP proxy module
--with-mail_ssl_module enable njt_mail_ssl_module
--without-mail_pop3_module disable njt_mail_pop3_module
--without-mail_imap_module disable njt_mail_imap_module
--without-mail_smtp_module disable njt_mail_smtp_module
--with-stream enable TCP/UDP proxy module
--with-stream=dynamic enable dynamic TCP/UDP proxy module
--with-stream_ssl_module enable njt_stream_ssl_module
--with-stream_realip_module enable njt_stream_realip_module
--with-stream_geoip_module enable njt_stream_geoip_module
--with-stream_geoip_module=dynamic enable dynamic njt_stream_geoip_module
--with-stream_ssl_preread_module enable njt_stream_ssl_preread_module
--without-stream_limit_conn_module disable njt_stream_limit_conn_module
--without-stream_access_module disable njt_stream_access_module
--without-stream_geo_module disable njt_stream_geo_module
--without-stream_map_module disable njt_stream_map_module
--without-stream_split_clients_module
disable njt_stream_split_clients_module
--without-stream_return_module disable njt_stream_return_module
--without-stream_set_module disable njt_stream_set_module
--without-stream_upstream_hash_module
disable njt_stream_upstream_hash_module
--without-stream_upstream_least_conn_module
disable njt_stream_upstream_least_conn_module
--without-stream_upstream_random_module
disable njt_stream_upstream_random_module
--without-stream_upstream_zone_module
disable njt_stream_upstream_zone_module
--with-google_perftools_module enable njt_google_perftools_module
--with-cpp_test_module enable njt_cpp_test_module
--add-module=PATH enable external module
--add-dynamic-module=PATH enable dynamic external module
--with-compat dynamic modules compatibility
--with-ntls enable NTLS support
--with-cc=PATH set C compiler pathname
--with-cpp=PATH set C preprocessor pathname
--with-cc-opt=OPTIONS set additional C compiler options
--with-ld-opt=OPTIONS set additional linker options
--with-cpu-opt=CPU build for the specified CPU, valid values:
pentium, pentiumpro, pentium3, pentium4,
athlon, opteron, sparc32, sparc64, ppc64
--without-pcre disable PCRE library usage
--with-pcre force PCRE library usage
--with-pcre=DIR set path to PCRE library sources
--with-pcre-opt=OPTIONS set additional build options for PCRE
--with-pcre-conf-opt=OPTIONS set additional configure options for PCRE
--with-pcre-jit build PCRE with JIT compilation support
--without-pcre2 do not use PCRE2 library
--with-zlib=DIR set path to zlib library sources
--with-zlib-opt=OPTIONS set additional build options for zlib
--with-zlib-asm=CPU use zlib assembler sources optimized
for the specified CPU, valid values:
pentium, pentiumpro
--with-libatomic force libatomic_ops library usage
--with-libatomic=DIR set path to libatomic_ops library sources
--with-openssl=DIR set path to OpenSSL library sources
--with-openssl-opt=OPTIONS set additional build options for OpenSSL
--with-debug enable debug logging
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
可以看到有各种选项,各种功能的开关。
我们再来看一下nginx源码的编译配置:
root@zhenghui-tx:~/soft/nginx-1.23.4# ./configure --help
--help print this message
--prefix=PATH set installation prefix
--sbin-path=PATH set nginx binary pathname
--modules-path=PATH set modules path
--conf-path=PATH set nginx.conf pathname
--error-log-path=PATH set error log pathname
--pid-path=PATH set nginx.pid pathname
--lock-path=PATH set nginx.lock pathname
--user=USER set non-privileged user for
worker processes
--group=GROUP set non-privileged group for
worker processes
--build=NAME set build name
--builddir=DIR set build directory
--with-select_module enable select module
--without-select_module disable select module
--with-poll_module enable poll module
--without-poll_module disable poll module
--with-threads enable thread pool support
--with-file-aio enable file AIO support
--with-http_ssl_module enable ngx_http_ssl_module
--with-http_v2_module enable ngx_http_v2_module
--with-http_realip_module enable ngx_http_realip_module
--with-http_addition_module enable ngx_http_addition_module
--with-http_xslt_module enable ngx_http_xslt_module
--with-http_xslt_module=dynamic enable dynamic ngx_http_xslt_module
--with-http_image_filter_module enable ngx_http_image_filter_module
--with-http_image_filter_module=dynamic
enable dynamic ngx_http_image_filter_module
--with-http_geoip_module enable ngx_http_geoip_module
--with-http_geoip_module=dynamic enable dynamic ngx_http_geoip_module
--with-http_sub_module enable ngx_http_sub_module
--with-http_dav_module enable ngx_http_dav_module
--with-http_flv_module enable ngx_http_flv_module
--with-http_mp4_module enable ngx_http_mp4_module
--with-http_gunzip_module enable ngx_http_gunzip_module
--with-http_gzip_static_module enable ngx_http_gzip_static_module
--with-http_auth_request_module enable ngx_http_auth_request_module
--with-http_random_index_module enable ngx_http_random_index_module
--with-http_secure_link_module enable ngx_http_secure_link_module
--with-http_degradation_module enable ngx_http_degradation_module
--with-http_slice_module enable ngx_http_slice_module
--with-http_stub_status_module enable ngx_http_stub_status_module
--without-http_charset_module disable ngx_http_charset_module
--without-http_gzip_module disable ngx_http_gzip_module
--without-http_ssi_module disable ngx_http_ssi_module
--without-http_userid_module disable ngx_http_userid_module
--without-http_access_module disable ngx_http_access_module
--without-http_auth_basic_module disable ngx_http_auth_basic_module
--without-http_mirror_module disable ngx_http_mirror_module
--without-http_autoindex_module disable ngx_http_autoindex_module
--without-http_geo_module disable ngx_http_geo_module
--without-http_map_module disable ngx_http_map_module
--without-http_split_clients_module disable ngx_http_split_clients_module
--without-http_referer_module disable ngx_http_referer_module
--without-http_rewrite_module disable ngx_http_rewrite_module
--without-http_proxy_module disable ngx_http_proxy_module
--without-http_fastcgi_module disable ngx_http_fastcgi_module
--without-http_uwsgi_module disable ngx_http_uwsgi_module
--without-http_scgi_module disable ngx_http_scgi_module
--without-http_grpc_module disable ngx_http_grpc_module
--without-http_memcached_module disable ngx_http_memcached_module
--without-http_limit_conn_module disable ngx_http_limit_conn_module
--without-http_limit_req_module disable ngx_http_limit_req_module
--without-http_empty_gif_module disable ngx_http_empty_gif_module
--without-http_browser_module disable ngx_http_browser_module
--without-http_upstream_hash_module
disable ngx_http_upstream_hash_module
--without-http_upstream_ip_hash_module
disable ngx_http_upstream_ip_hash_module
--without-http_upstream_least_conn_module
disable ngx_http_upstream_least_conn_module
--without-http_upstream_random_module
disable ngx_http_upstream_random_module
--without-http_upstream_keepalive_module
disable ngx_http_upstream_keepalive_module
--without-http_upstream_zone_module
disable ngx_http_upstream_zone_module
--with-http_perl_module enable ngx_http_perl_module
--with-http_perl_module=dynamic enable dynamic ngx_http_perl_module
--with-perl_modules_path=PATH set Perl modules path
--with-perl=PATH set perl binary pathname
--http-log-path=PATH set http access log pathname
--http-client-body-temp-path=PATH set path to store
http client request body temporary files
--http-proxy-temp-path=PATH set path to store
http proxy temporary files
--http-fastcgi-temp-path=PATH set path to store
http fastcgi temporary files
--http-uwsgi-temp-path=PATH set path to store
http uwsgi temporary files
--http-scgi-temp-path=PATH set path to store
http scgi temporary files
--without-http disable HTTP server
--without-http-cache disable HTTP cache
--with-mail enable POP3/IMAP4/SMTP proxy module
--with-mail=dynamic enable dynamic POP3/IMAP4/SMTP proxy module
--with-mail_ssl_module enable ngx_mail_ssl_module
--without-mail_pop3_module disable ngx_mail_pop3_module
--without-mail_imap_module disable ngx_mail_imap_module
--without-mail_smtp_module disable ngx_mail_smtp_module
--with-stream enable TCP/UDP proxy module
--with-stream=dynamic enable dynamic TCP/UDP proxy module
--with-stream_ssl_module enable ngx_stream_ssl_module
--with-stream_realip_module enable ngx_stream_realip_module
--with-stream_geoip_module enable ngx_stream_geoip_module
--with-stream_geoip_module=dynamic enable dynamic ngx_stream_geoip_module
--with-stream_ssl_preread_module enable ngx_stream_ssl_preread_module
--without-stream_limit_conn_module disable ngx_stream_limit_conn_module
--without-stream_access_module disable ngx_stream_access_module
--without-stream_geo_module disable ngx_stream_geo_module
--without-stream_map_module disable ngx_stream_map_module
--without-stream_split_clients_module
disable ngx_stream_split_clients_module
--without-stream_return_module disable ngx_stream_return_module
--without-stream_set_module disable ngx_stream_set_module
--without-stream_upstream_hash_module
disable ngx_stream_upstream_hash_module
--without-stream_upstream_least_conn_module
disable ngx_stream_upstream_least_conn_module
--without-stream_upstream_random_module
disable ngx_stream_upstream_random_module
--without-stream_upstream_zone_module
disable ngx_stream_upstream_zone_module
--with-google_perftools_module enable ngx_google_perftools_module
--with-cpp_test_module enable ngx_cpp_test_module
--add-module=PATH enable external module
--add-dynamic-module=PATH enable dynamic external module
--with-compat dynamic modules compatibility
--with-cc=PATH set C compiler pathname
--with-cpp=PATH set C preprocessor pathname
--with-cc-opt=OPTIONS set additional C compiler options
--with-ld-opt=OPTIONS set additional linker options
--with-cpu-opt=CPU build for the specified CPU, valid values:
pentium, pentiumpro, pentium3, pentium4,
athlon, opteron, sparc32, sparc64, ppc64
--without-pcre disable PCRE library usage
--with-pcre force PCRE library usage
--with-pcre=DIR set path to PCRE library sources
--with-pcre-opt=OPTIONS set additional build options for PCRE
--with-pcre-jit build PCRE with JIT compilation support
--without-pcre2 do not use PCRE2 library
--with-zlib=DIR set path to zlib library sources
--with-zlib-opt=OPTIONS set additional build options for zlib
--with-zlib-asm=CPU use zlib assembler sources optimized
for the specified CPU, valid values:
pentium, pentiumpro
--with-libatomic force libatomic_ops library usage
--with-libatomic=DIR set path to libatomic_ops library sources
--with-openssl=DIR set path to OpenSSL library sources
--with-openssl-opt=OPTIONS set additional build options for OpenSSL
--with-debug enable debug logging
root@zhenghui-tx:~/soft/nginx-1.23.4#
如果你深入使用过nginx或者自己编译过nginx的话,是可以直接上手OpenNJet 。
我在编译的时候,比较喜欢创建一个脚本,在脚本里写构建的脚本代码,这样有助于后期查看:
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# touch build.sh
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
如果初次不太了解的话,执行最简单的语法,先让项目跑起来即可,后期再根据自己需求增加编译选项:
我比较喜欢使用–prefix选项,因为这样比较方便自己维护安装的目录,如果每一个项目都安装到系统的/lib或/usr等系统目录中,可能会造成乱象。编译自己其他项目时可能会出错,也很难排查。
用过C和C++的朋友应该都懂这个,其实就是lib库的链接问题,include引用错路径的问题等等。
./configure --prefix=`pwd`/_install
庆幸的是,官方提供的build的脚本,我们可以直接使用:
./build_cc.sh conf
如下结果就是成功了:
执行make:
报错:
make[3]: Entering directory '/root/soft/build_OpenNJet/njet-v2.1.0/auto/lib/tongsuo'
gcc -I. -Iinclude -Icrypto/ec/curve448/arch_32 -Icrypto/ec/curve448 -fPIC -m64 -Wa,--noexecstack -Wall -O3 -DDEBUG_UNUSED -DPEDANTIC -pedantic -Wno-long-long -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wswitch -Wsign-compare -Wshadow -Wformat -Wtype-limits -Wundef -Werror -Wmissing-prototypes -Wstrict-prototypes -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DOPENSSLDIR="\"/root/soft/build_OpenNJet/njet-v2.1.0/auto/lib/tongsuo/.openssl/ssl\"" -DENGINESDIR="\"/root/soft/build_OpenNJet/njet-v2.1.0/auto/lib/tongsuo/.openssl/lib/engines-1.1\"" -DNDEBUG -MMD -MF crypto/ec/curve448/f_generic.d.tmp -MT crypto/ec/curve448/f_generic.o -c -o crypto/ec/curve448/f_generic.o crypto/ec/curve448/f_generic.c
crypto/ec/curve448/f_generic.c:21:27: error: argument 1 of type 'uint8_t[56]' {aka 'unsigned char[56]'} with mismatched bound [-Werror=array-parameter=]
21 | void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_hibit)
| ~~~~~~~~^~~~~~~~~~~~~~~~~
In file included from crypto/ec/curve448/f_generic.c:12:
crypto/ec/curve448/field.h:65:28: note: previously declared as 'uint8_t *' {aka 'unsigned char *'}
65 | void gf_serialize(uint8_t *serial, const gf x, int with_highbit);
| ~~~~~~~~~^~~~~~
cc1: all warnings being treated as errors
make[3]: *** [Makefile:2830: crypto/ec/curve448/f_generic.o] Error 1
make[3]: Leaving directory '/root/soft/build_OpenNJet/njet-v2.1.0/auto/lib/tongsuo'
make[2]: *** [Makefile:176: all] Error 2
make[2]: Leaving directory '/root/soft/build_OpenNJet/njet-v2.1.0/auto/lib/tongsuo'
make[1]: *** [objs/Makefile:5184: auto/lib/tongsuo/.openssl/include/openssl/ssl.h] Error 2
make[1]: Leaving directory '/root/soft/build_OpenNJet/njet-v2.1.0'
make: *** [Makefile:10: build] Error 2
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# find ./ -name "f_generic.c"
./auto/lib/tongsuo/crypto/ec/curve448/f_generic.c
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# vim ./auto/lib/tongsuo/crypto/ec/curve448/f_generic.c
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# vim ./auto/lib/tongsuo/crypto/ec/curve448/f_generic.c + 21
2 files to edit
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# vim ./auto/lib/tongsuo/crypto/ec/curve448/f_generic.c +21
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
可以看到.h和.c文件中的参数类型不匹配,一个是数组,一个是指针:
特意查了一下,openssl是有提交补丁的:
https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=7217decc7c454eec4a6d4ce163ac44b4558fe03b
修改之后的:
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# vim ./auto/lib/tongsuo/crypto/ec/curve448/f_generic.c +21
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# grep -nr "gf_serialize" ./auto/lib/tongsuo/crypto/ec/curve448/
grep: ./auto/lib/tongsuo/crypto/ec/curve448/f_generic.o: binary file matches
./auto/lib/tongsuo/crypto/ec/curve448/f_generic.c:21://void gf_serialize(uint8_t serial[], const gf x, int with_hibit)
./auto/lib/tongsuo/crypto/ec/curve448/f_generic.c:22:void gf_serialize(uint8_t *serial, const gf x, int with_hibit)
grep: ./auto/lib/tongsuo/crypto/ec/curve448/curve448.o: binary file matches
./auto/lib/tongsuo/crypto/ec/curve448/curve448.c:311: gf_serialize(enc, x, 1);
./auto/lib/tongsuo/crypto/ec/curve448/curve448.c:444: gf_serialize(out, x1, 1);
./auto/lib/tongsuo/crypto/ec/curve448/curve448.c:468: gf_serialize(out, q->y, 1);
./auto/lib/tongsuo/crypto/ec/curve448/field.h:65:void gf_serialize(uint8_t *serial, const gf x, int with_highbit);
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
再次make:
又报了错误,报错如下:
gcc -I. -Iinclude -fPIC -m64 -Wa,--noexecstack -Wall -O3 -DDEBUG_UNUSED -DPEDANTIC -pedantic -Wno-long-long -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wswitch -Wsign-compare -Wshadow -Wformat -Wtype-limits -Wundef -Werror -Wmissing-prototypes -Wstrict-prototypes -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DOPENSSLDIR="\"/root/soft/build_OpenNJet/njet-v2.1.0/auto/lib/tongsuo/.openssl/ssl\"" -DENGINESDIR="\"/root/soft/build_OpenNJet/njet-v2.1.0/auto/lib/tongsuo/.openssl/lib/engines-1.1\"" -DNDEBUG -MMD -MF ssl/s3_cbc.d.tmp -MT ssl/s3_cbc.o -c -o ssl/s3_cbc.o ssl/s3_cbc.c
In file included from /usr/include/string.h:535,
from include/internal/constant_time.h:14,
from ssl/s3_cbc.c:10:
In function 'memcpy',
inlined from 'ssl3_cbc_digest_record' at ssl/s3_cbc.c:379:13:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:29:10: error: '__builtin___memcpy_chk' offset [64, 128] is out of the bounds [0, 13] [-Werror=array-bounds]
29 | return __builtin___memcpy_chk (__dest, __src, __len,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30 | __glibc_objsize0 (__dest));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[3]: *** [Makefile:6149: ssl/s3_cbc.o] Error 1
make[3]: Leaving directory '/root/soft/build_OpenNJet/njet-v2.1.0/auto/lib/tongsuo'
make[2]: *** [Makefile:176: all] Error 2
make[2]: Leaving directory '/root/soft/build_OpenNJet/njet-v2.1.0/auto/lib/tongsuo'
make[1]: *** [objs/Makefile:5184: auto/lib/tongsuo/.openssl/include/openssl/ssl.h] Error 2
make[1]: Leaving directory '/root/soft/build_OpenNJet/njet-v2.1.0'
make: *** [Makefile:10: build] Error 2
很无奈,一些编译问题,不得不让我放弃了这一条选择。
这是我的编译机的一些基本信息:
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# uname -a
Linux zhenghui-tx 5.15.0-79-generic #86-Ubuntu SMP Mon Jul 10 16:07:21 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0# g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-11-XeT9lY/gcc-11-11.4.0/debian/tmp-gcn/usr --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
root@zhenghui-tx:~/soft/build_OpenNJet/njet-v2.1.0#
最终编译安装这个环境以失败告终,这个编译的问题我认为是官方必须要搞定的,也提了相关Issues 感兴趣的可以看一下: https://github.com/OpenNJet/OpenNJet/issues/4
官方人员也是很积极的回复了,说之后的版本会提升tongsuo到8.4.0:
很期待下一个版本,下个版本出来后,我再来深入探究一下。
如何使用docker搭建一个开发环境
对于一个玩C&C++的人来说,这一项技能是必须的,因为开发环境用docker最简单了,还可以隔离宿主机的各种环境,互不干扰。
1、下载源码
国内推荐从gitee上下载:https://gitee.com/njet-rd
国外推荐从github上下载:https://github.com/OpenNJet/OpenNJet
2、因为njet本身就提供了Dockerfile,所以天生就支持了:
构建docker镜像:
docker build -t njet_main:v1.0 .
执行后如果能查出来说明构建成功了:
zhenghui@zh-pc:njet$ sudo docker images |grep njet
njet_main v1.0 784bed5f0897 2 minutes ago 520MB
zhenghui@zh-pc:njet$
运行:
docker run -v `pwd`:/njet_main njet_main:v1.0 /bin/bash -c "cd /njet_main && ./build_cc.sh conf make"
其实可以分成2个步骤:
1、后台一直跑着这个docker即可:
zhenghui@zh-pc:njet$ sudo docker run -td -v `pwd`:/njet_main njet_main:v1.0 /bin/bash
3c626ddc91eee718ef8044238626a28616e614b7db39245ef3321cdf1e64bdba
zhenghui@zh-pc:njet$
2、需要的时候进入:
zhenghui@zh-pc:njet$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3c626ddc91ee njet_main:v1.0 "/bin/bash" 2 minutes ago Up 2 minutes
3、进入docker
3c626ddc91ee ID就是进入docker的必要条件之一:
zhenghui@zh-pc:njet$ sudo docker exec -it 3c626ddc91ee /bin/bash
[root@3c626ddc91ee /]#
[root@3c626ddc91ee /]#
下面就是进入docker后的:
[root@3c626ddc91ee /]# cd /njet_main/
[root@3c626ddc91ee njet_main]#
[root@3c626ddc91ee njet_main]# pwd
/njet_main
[root@3c626ddc91ee njet_main]# ls
CHANGES CHANGES.ru Dockerfile Dockerfile.ubuntu LICENSE Makefile NOTICE README README.md auto build build_cc.sh build_k8s.sh build_lua.sh conf configure contrib doc html img luajit lualib man modules modules_dynamic modules_static njet_sidecar.conf objs repos scripts src
[root@3c626ddc91ee njet_main]#
[root@3c626ddc91ee njet_main]#
4、编译
cd /njet_main
./build_cc.sh conf make
docker还是比较方便的,用官方提供的Dockerfile生成的docker镜像,一下子就成功了,对于开发者来说,或者二次开发者进行二次开发来说很方便。起码不让你为了编译环境不一致而烦恼。
开发时可以采用“宿主机编辑代码”+“Docker上编译代码”这个方案。
因为我平时工作时也是这样做的,很方便。
总结
本次体验OpenNjet好像开盲盒一样,一个一个的惊喜扑面而来。我从2个角度来总结一下对OpenNjet的初体验。
1、使用者角度
- 上手快:对于使用者来说,如果使用者用过NGINX的话,用njet可以说是秒秒钟上手,真的很容易。因为一些相关的配置可以很完美的和NGINX融合,也可以看作为向下兼容。对于用户来说,我认为上手快就是一大特点。
- 易用:为什么说是易用呢,因为njet提供了多种配置njet的方式,还增加了动态配置的功能,拿API接口来说吧,这一点就打败了市场上很多普通web服务器,当然了njet也不能和普通的web服务器做对比,因为njet的口号是:让用户永远在线!
- 第三方用户友好:因为有动态配置,再加上njet的口号:让用户永远在线!很明显的可以体验出来,对于第三方用户是无感的,企业修改一些配置,第三方用户如何还在进行着操作,此时是不受影响的,没有丝毫感觉。本文也体现njet的愿景:让用户永远在线!
- 可以基于Docker部署比较灵活;
- 可以支持HTTP/3;
2、开发者角度
- 开发环境灵活:提供了多种开发环境的支持,这一点比较灵活。例如我本次想使用系统直接编译开发呢,结果失败了,就换了一种docker的方式,就一下子成功了。这就是灵活性。
- 二次开发简单:因为njet提供了一系列的API接口,如果要对接到自己的dev系统中,是很简单的事情,直接调API接口即可,针对DevOps很方便。
- 完全适配NGINX用户:因为njet是基于NGINX做的二次开发,所以njet完全适配NGINX,所以完全适配NGINX用户。对NGINX做过二次开发的开发者来说,这一点也是值得肯定的。