Skip to content

Instantly share code, notes, and snippets.

@ericluoliu
Last active March 31, 2023 11:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericluoliu/defa835dccf44a6c11db7bd72f88f10c to your computer and use it in GitHub Desktop.
Save ericluoliu/defa835dccf44a6c11db7bd72f88f10c to your computer and use it in GitHub Desktop.
Apache APISIX Java Plugin Runner Improvement (GSoC 2022)

Apache APISIX Java Plugin Runner Improvement (GSoC 2022)

  • By: Eric Liu

  • Mentors: Zeping Bai, Zhiyuan Ju, ZhengSong Tu (tzssangglass)

Project Description

This project's aim was to improve upon the current apisix-java-plugin-runner design. APISIX is an API Gateway that provides traffic management (load balancing, authorization, security, etc). Users can develop their own custom plugins, however, the current development process for Java plugins is inconvenient and unreliable. This project streamlines and improves the Java plugin development and shipment process.

Current State and Future Works

The apisix-java-plugin-runner is not in its final state. The apisix-java-plugin-runner can stably run Java plugins, however, a significant work item that must still be completed is implementing Isolated Classloading. Through this project, apisix-java-plugin-runner can now run multiple plugins that were pulled from different locations. This also means that version mismatches can occur within the nested dependencies of different plugins (class shadowing), causing potential build errors. Another (optional) work item would be to expand plugin-compatability to other JVM based languages besides for Java.

Completed Work Items

Cloned Repository: https://github.com/ericluoliu/apisix-java-plugin-runner

Deployed apisix-java-plugin-runner to Maven Central as a nested Spring Boot UberJAR

Allows Java developers to run the apisix-java-plugin-runner process as Maven dependency rather than from source code

Relevant PR: apache/apisix-java-plugin-runner#155

Documentation: apache/apisix-java-plugin-runner#160

Maven Central JAR: https://search.maven.org/search?q=g:org.apache.apisix

Created streamlined plugin deployment/shipment process

Allows Java developers to:

  • Easily ship their plugin to Maven as a non-executable JAR
  • Use deployed plugins by injecting it as a Spring Bean
  • Build/run multiple plugins

Relevant repository: https://github.com/ericluoliu/java-plugin-runner-demo

Documentation:

Implemented custom dynamic class-loader to support hot reloading

Speed up plugin development process

Relevant PRs:

Documentation: apache/apisix-java-plugin-runner#166

Incomplete Work Items

Provide support for isolated class-loading to prevent version mismatch in multi-plugin projects

Isolated class-loading was unable to be implemented. Three solutions were tried:

  1. Implement custom class-loader and load each plugin independently
    Why it failed: Spring Boot uses the LaunchedUrlClassLoader to load BOOT-INF/ classes and jars into the application. Overriding the LaunchedUrlClassLoader with my own custom classloader is unfeasible.

  2. Use SofaARK, a thrid party isolated classloader framework
    Why it failed: Tried to incorporate SofaARK into project. Ran into errors after errors. Also, SofaARK documentation mentions that SofaARK only supports integration into simple, single-module project. Overall, SofaARK lacks documentation and is confusing to follow.

  3. Use SofaBOOT Module, a third party isolated module loader
    Why it failed: Provided by the same organization as the one above. SofaBOOT Module was clearly in its early stages of development. Virtually no documentation available and almost no resources online referring to it.

Challenges

The hardest part of this project was implementing dynamic class-loading and isolated class-loading.

I read a lot of documentation and guides for dynamic class-loading, but when I tried implementing it into the apisix-java-plugin-runner, it did not work. I used all my resources imaginable, asking my mentors, going on Google, StackOverflow, etc., but for a few days I seemed to be getting nowhere. There was very minimal information online about implementing dynamic classloading for a Spring Boot project and the guides that were available were not specific to what I wanted.

Ultimately, I just had to be creative and try stuff on my own. I had a decent idea of how Spring Boot worked, and this allowed me to hypothesize how hot reloading might look within a Spring Application.

Inside of Spring Boot applications are something called Spring Beans, and each Spring Bean represents a loaded class. So when a project boots, the Java classes are loaded. Each class is placed into a bean, and the beans are then loaded. I concluded that for dynamic classloading to work in a SpringBoot project, it was necessary to not only dynamically reload the class but also reload the bean that corresponded to the class.

After spending some time trying to implement this and patching random bugs, hot reloading of Java plugins finally worked!

Thanks

Thanks to my main point of contact, ZhengSong, who frequently met with me to discuss progress, provide checkpoints, and give future guidelines. Could not have completed this project without him!

Thanks to Nicolas for giving me critical feedback and insight on various parts of my work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment