Make writing a habit together! This is the 14th day of my participation in the “Gold Digging Day New Plan · April More Text Challenge”. Click here for more details.

Welcome to my GitHub

Here classification and summary of xinchen all original (including supporting source code) : github.com/zq2599/blog…

About Nginx extensions

  • In the case of Chen himself, nginx is no stranger to a Java programmer, and the following is probably the most common usage scenario, reverse proxy:

  • In addition to reverse proxies, nGINx’s modularization mechanism provides nginx with rich features such as ngx_HTTP_log_module (logging) and ngx_HTTP_rewrite_module (redirection)
  • In addition to the official module, there are many powerful third-party modules can choose, the diagram below, more details refer to: www.nginx.com/resources/w…

  • In this sense, secondary development on Nginx is not a mystery, and we can also customize and extend nginx functionality to our own needs
  • However, when you open the official development document, it looks like this:

  • Nginx’s custom modules are developed in C, however, Hinchen is just a Java programmer who knows CRUD
  • Thanks to the nginx-Clojure module, it supports functionality extensions to Nginx using Java:

  • Learn the Nginx-Clojure module from beginner to master, unlock the power of Clojure, and master the technology of extending Nginx with Java

This paper gives an overview of

  • As the beginning of the Java Extension Nginx series, this article will continue The original style of Hinchen: to provide you with a basic understanding of the Nginx-Clojure module in minimal time and minimal functionality
  • This paper consists of the following parts:
  1. Introduce nginx – clojure
  2. In actual combat
  3. validation

Introduce nginx – clojure

  • Nginx-clojure is a third-party nginx module, Nginx module for Embedding Clojure/Java/Groovy Programs, typically those Ring based Handlers
  • The nginx-Clojure module supports embedded Clojure(closure), Java, Groovy, and other ring-based handlers.
  • Ring in Clojure is a low-level interface and library for building Web applications. It is similar to the Ruby Rack, Python WSGI or Java Servlet specifications
  • From a Java developer’s point of view, this means developing an implementation class for Nginx JavaringHandler that can then be run in the Nginx-Clojure module
  • The latest version of nginx-Clojure is v0.5.2. The official website is nginx-Clojure.github
  • That’s it for nginx-Clojure

Actual combat Function introduction

  • Although Nginx-Clojure supports a lot of features, this article will focus on the classic Hello World and save more for later articles in the Java Extensions Nginx series
  • Today’s actual combat, the effect below. Let’s write the HelloHandler. Java and configuration, and then use the browser after a request, the HelloHandler code will be executed, the browser will receive HelloHandler returned content:

  • Today’s actual steps are as follows:

  • Thank you for listening to me for so long. Now, let’s get started

Environmental information

  • Here is my actual combat environment information for your reference, this environment can normally operate all combat:
  1. Operating system: macOS Big Sur 11.5.2 (20G95)
  2. The JDK: 1.8.0 comes with _281
  3. Maven: 3.8.1

Download the nginx package that integrates the Nginx-Clojure module

  • The first thing we need to do is download a special Nginx, which is special because it integrates the Nginx-Clojure module right out of the box
  • Download address: sourceforge.net/projects/ng… In the red box below, I selected the latest version 0.5.2:

Unpack the nginx package

  • Nginx-clojure-0.5.2: Nginx-Clojure-0.5.2: Nginx-Clojure-0.5.2

  • Next, rename the executable file based on your operating system. I’m on macOS, so rename nginx-MacOSx to nginx, and if it’s Linux, rename nginx-linux-64 to nginx, if it’s Windows, Rename nginx-win64.exe to nginx.exe
  • The above renaming operation is officially recommended by Nginx-Clojure to unify the executable file name, so that the command running in the document is unified
  • Run the./nginx -v command and the console responds as follows:
./nginx -v
nginx version: nginx/1.18.0
Copy the code

Code, develop the Java version of handler

  • To start writing code, create a new Maven project (I’ll call it simple-Hello), configure the Repository node in POM.xml, and the unique dependency nginx-Clojure, as shown below:
<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>
Copy the code
  • The invoke method returns an array containing only three elements: the return code, the set of key-value pairs for the response header, and the body of the response:
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}; }}Copy the code
  • At this point, the coding is complete, Hinchen master Hello World is not for nothing…

Compile and generate the JAR

  • If you run MVN clean package -u in the pom. XML directory, you will generate a jar package in the target directory, which is only 3K in size:

Put the jar into the jars directory of nginx

  • Place the simply-Hello-1.0-snapshot. jar file you generated earlier into the jars folder in the red box below:

Modify nginx configuration

  • Nginx-clojure-0.5.2 /conf/nginx.conf/nginx-clojure-0.5.2/conf/nginx.
location /java {
         content_handler_type 'java';
         content_handler_name 'com.bolingcavalry.simplehello.HelloHandler';
}
Copy the code
  • Nginx. conf contains a number of java-related configurations, which we will leave unchanged in this article.

###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;
    
    Jars for nginx-Clojure runtime jars. Jars for Nginx-Clojure runtime jars. Jars for Nginx-Clojure runtime Jars
    ### 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
      
        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
#}
#}
# ';
#}
#         }}Copy the code

7. Start the nginx

  • The startup command is simple, run in the nginx-clojure-0.5.2 directory./nginx
  • Nginx-clojure-0.5.2 /logs/error.log if the startup fails, open nginx-clojure-0.5.2/logs/error.log to view the problem.
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()Copy the code

Validation 8.

  • Open the postman validation service is normal, request the address is http://127.0.0.1:8080/java
  • The response looks like the following, as expected, and returns the contents of our custom HelloHandler

  • At this point, the beginning of nginx-Clojure is complete, a few lines of code, but a window for Java programmers to extend Nginx with familiar technologies and participate in the rich nginx ecosystem

Is it in the right direction? A little personal thought

  • Writing Java code on nginx makes it possible for Nginx to be coupled to the business. Experienced users will notice that this is a dangerous trend. After all, Nginx is approaching the outermost layer of backend services, and stability is the primary concern. Independent deployment of business functions is a common solution in production environments:

  • Is it appropriate to write Java code on Nginx? He had no definitive answer, but he could draw inspiration from the great God’s work
  • Kaitao daisen’s “Follow me to Learn Nginx+Lua Development” tells how to use OpenResty to develop with Lua on Nginx, which is suitable for Web applications, access gateways, Web firewalls, cache servers and other scenarios. There is also a detailed description in the physical book “Core Technologies of Website Architecture with Hundreds of millions of traffic”, such as jingdong commodity details page. It is directly returned by reading the cache on Nginx
  • To sum up, The business logic will not be implemented on Nginx because of the learning of this technology, but in caching, authentication and other scenarios, you can consider using familiar Java to implement on Nginx
  • Nginx-clojure nginx-Clojure Nginx-Clojure Nginx-Clojure

Download the source code

  • The full Java Extension Nginx source code can be downloaded at GitHub with the following address and link information (github.com/zq2599/blog…
The name of the link note
Project home page Github.com/zq2599/blog… The project’s home page on GitHub
Git repository address (HTTPS) Github.com/zq2599/blog… The project source warehouse address, HTTPS protocol
Git repository address (SSH) [email protected]:zq2599/blog_demos.git The project source warehouse address, SSH protocol
  • The git project has multiple folders. The source code for this project is in the nginx-Clojure-tutorials folder, as shown in the red box below:

Welcome to the Nuggets: programmer Chen Chen

Learning on the road, you are not alone, Xinchen original all the way accompanied by…