前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenNJet如何做到让用户永远在线

OpenNJet如何做到让用户永远在线

作者头像
手撕代码八百里
发布2024-05-24 13:12:18
470
发布2024-05-24 13:12:18
举报
文章被收录于专栏:猿计划猿计划

前言

最近看到了国内开源的一个名为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、下载好的:

代码语言:javascript
复制
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进行安装

代码语言:javascript
复制
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的方式。

安装位置:

代码语言:javascript
复制
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服务了:

代码语言:javascript
复制
systemctl start njet #启动服务
systemctl stop njet #停止服务

查看是否启动成功

代码语言:javascript
复制
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/

出现如下界面既成功:

停止服务:

代码语言:javascript
复制
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根目录的位置也是可以修改的:

代码语言:javascript
复制
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的目录:

代码语言:javascript
复制
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实时监控日志,看看日志是不是真的生效了:

image.png
image.png

此时可以刷新下web界面,可以看到日志哗啦啦的就出来了。

这就是动态配置的作用,不必重启。

编译安装

如果你是ubuntu需要安装如下:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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#

解压:

代码语言:javascript
复制
root@zhenghui-tx:~/soft/build_OpenNJet#
root@zhenghui-tx:~/soft/build_OpenNJet# tar -zxvf njet-v2.1.0.tar.gz

解压后:

代码语言:javascript
复制
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文档,然后就是看编译配置脚本:

代码语言:javascript
复制
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源码的编译配置:

代码语言:javascript
复制
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

我在编译的时候,比较喜欢创建一个脚本,在脚本里写构建的脚本代码,这样有助于后期查看:

代码语言:javascript
复制
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引用错路径的问题等等。

代码语言:javascript
复制
 ./configure --prefix=`pwd`/_install

庆幸的是,官方提供的build的脚本,我们可以直接使用:

代码语言:javascript
复制
./build_cc.sh conf

如下结果就是成功了:

image.png
image.png

执行make:

image.png
image.png

报错:

代码语言:javascript
复制
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文件中的参数类型不匹配,一个是数组,一个是指针:

image.png
image.png

特意查了一下,openssl是有提交补丁的: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=7217decc7c454eec4a6d4ce163ac44b4558fe03b

image.png
image.png

修改之后的:

代码语言:javascript
复制
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:

image.png
image.png

又报了错误,报错如下:

代码语言:javascript
复制
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

很无奈,一些编译问题,不得不让我放弃了这一条选择。 这是我的编译机的一些基本信息:

代码语言:javascript
复制
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:

image.png
image.png

很期待下一个版本,下个版本出来后,我再来深入探究一下。

如何使用docker搭建一个开发环境

对于一个玩C&C++的人来说,这一项技能是必须的,因为开发环境用docker最简单了,还可以隔离宿主机的各种环境,互不干扰。

1、下载源码 国内推荐从gitee上下载:https://gitee.com/njet-rd 国外推荐从github上下载:https://github.com/OpenNJet/OpenNJet

2、因为njet本身就提供了Dockerfile,所以天生就支持了:

image.png
image.png

构建docker镜像:

代码语言:javascript
复制
docker build -t njet_main:v1.0 .

执行后如果能查出来说明构建成功了:

代码语言:javascript
复制
zhenghui@zh-pc:njet$ sudo docker  images |grep njet
njet_main               v1.0      784bed5f0897   2 minutes ago   520MB
zhenghui@zh-pc:njet$ 

运行:

代码语言:javascript
复制
docker run -v `pwd`:/njet_main njet_main:v1.0 /bin/bash -c "cd /njet_main && ./build_cc.sh conf make"

其实可以分成2个步骤: 1、后台一直跑着这个docker即可:

代码语言:javascript
复制
zhenghui@zh-pc:njet$ sudo docker run -td -v `pwd`:/njet_main njet_main:v1.0 /bin/bash 
3c626ddc91eee718ef8044238626a28616e614b7db39245ef3321cdf1e64bdba
zhenghui@zh-pc:njet$ 

2、需要的时候进入:

代码语言:javascript
复制
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的必要条件之一:

代码语言:javascript
复制
zhenghui@zh-pc:njet$ sudo docker exec -it 3c626ddc91ee /bin/bash
[root@3c626ddc91ee /]# 
[root@3c626ddc91ee /]# 

下面就是进入docker后的:

代码语言:javascript
复制
[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、编译

代码语言:javascript
复制
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做过二次开发的开发者来说,这一点也是值得肯定的。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Ubuntu通过deb包安装
  • 功能体验
    • 1、如何控制njet服务
      • 2、如何部署自己的web网站
        • 3、使用API接口管理配置
          • 4、使用GUI管理配置
            • 5、http_log模块动态配置
            • 编译安装
            • 如何使用docker搭建一个开发环境
            • 总结
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档