GithubHelp home page GithubHelp logo

qianxingchuan / doraemon Goto Github PK

View Code? Open in Web Editor NEW
12.0 4.0 1.0 10.38 MB

2048乐队是一个很牛逼的乐队!这是一个轻量级的Java模块隔离框架

License: Apache License 2.0

Java 100.00%
module module-loader bundle-splitting bundle classloader-isolation classloader

doraemon's Introduction

简介

2017年,我在菜鸟物流云这个部门做了一个叫做Asgard的网关,当时为了快速实现,只适配了阿里巴巴的技术栈体系,比如鉴权的部分,直接把菜鸟的账号系统接入的代码固化在网关;再比如调用服务的部分,直接把泛化调用HSF的代码固化在网关。这些固化代码的方式,对于Asgard的可扩展性和灵活性都造成了无比巨大的限制。

从菜鸟离职之后,在2019年5月,在vivo做关于云存储相关的项目,vivo的基础设施不是特别完美,所以存在很多重复劳动,比如几乎每个web应用都会写一套一模一样的app鉴权、web鉴权,以及通用的cors的配置。这一点我非常不爽,所以决定在vivo重新把Asgard写一遍,这次重写,必定完善之前菜鸟物流云时期没有时间做的一些事情,比如高度可自定义每个调用阶段,再比如网关必须要支持响应式、全异步,以及支持websocket等等。

既然要实现高度自定义,那么我们需要有一套高度可插拔的plugin处理框架,osgi太重了,我不想我们的应用有太多这样的依赖,以及发布规范; 蚂蚁金服有一套开源的sofa-ark,也能满足我的要求,但是对于我来说,还是不够轻量级,我其实只要能在网关应用内部可以独立每个plugin即可,如图1: 图1

本文重点介绍我基于Java类加载器实现的一个轻量级模块隔离框架:Doraemon。 在同一个JVM里面,我们的应用程序可以调用任意一个bundle的export出来的实例,bundle互相之间不可见。

Doraemon快速使用

实现基于鉴权接口的不同实现

样例工程见doraemon-sample

主要工程: sample-auth-facade : 鉴权的接口定义 sample-auth-bundle1 : 基于鉴权接口的实现1 sample-auth-bundle2 : 基于鉴权接口的实现2 sample-auth-project : 运行bundle1和bundle2的主程序

bundle的实现

  1. 可以基于doraemon-project-archetype来构建你的代码骨架
  2. 生成的doraemon-bundle目录结构如图2

图2

bundle 的 pom.xml关键依赖如下:

...

    <dependencies>
        <!--业务的基本依赖 -->
        <dependency>
            <groupId>io.github.qianxingchuan.framework</groupId>
            <artifactId>sample-auth-facade</artifactId>
        </dependency>
        <!--每个bundle的依赖,每个bundle 必须要有一个 io.github.qianxingchuan.framework.doraemon.BundleService实例 -->
        <dependency>
            <groupId>io.github.qianxingchuan.framework</groupId>
            <artifactId>doraemon-facade</artifactId>
            <version>0.1-RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.4.RELEASE</version>
        </dependency>
    </dependencies>
...
</project>

bundle内部的实现,不限制框架,因为doraemon在运行每个bundle的时候是互相隔离的, 但是每个bundle必须要有一个类来实现io.github.qianxingchuan.framework.doraemon.BundleService,并且配置到 bundle.properties

bundle.properties配置如下:

init-class=io.github.qianxingchuan.doraemon.sample.auth.run.SampleBundleRun
skip-class=io.github.qianxingchuan.doraemon.sample.facade.AuthFacade

init-class 的意思就是bundle在初始化会自动执行这个里面的doIt方法

skip-class 的意思是该class不会由bundle的类加载器来加载

所以按照我们图1的表述,这个配置就是io.github.qianxingchuan.doraemon.sample.auth.run.SampleBundleRun由bundle1的模块类加载器来加载, io.github.qianxingchuan.doraemon.sample.facade.AuthFacade则由Application所在的类加载器来加载。

所有的代码写完之后,通过mvn clean compile package,即可生成一个 .zip 的bundle文件。 代码骨架的maven地址如下:

    <groupId>io.github.qianxingchuan.framework</groupId>
    <artifactId>doraemon-project-archetype</artifactId>
    <version>0.1-RELEASE</version>

bundle运行

参照sample-auth-project工程

doraemon's People

Contributors

qianxingchuan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

gangzhidong

doraemon's Issues

调用BundleBean方法得到了”No qualifying bean of type '<Facade Class名>' available“的报错

你好,
我尝试用SpringBoot作为启动程序做了个范例。在打印bundle path/打印ClassLoader的步骤都很顺利,但在调用实现了Facade接口的BundleBean方法的时候报错了如下的错误:

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.doraemon.facade.DemoFacade' available
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:352)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:343)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1127)
	at com.galaxy.demo.doraemon.bundle1.run.BundleRun.getBundleBean(BundleRun.java:30)

我的SpringBoot程序的代码如下,基本和范例中的main程序代码一致。

@SpringBootApplication
public class DoraemonDemoAppApplication {

	public static void main(String[] args) {
		SpringApplication.run(DoraemonDemoAppApplication.class, args);

		List<RunDoraemonBundle> runDoraemonBundles = new ArrayList<>();

		String bundle1Path = DoraemonDemoAppApplication.class.getResource("/doraemon-bundle1-1.0.0-SNAPSHOT-release.zip").getPath();
		String bundle2Path = DoraemonDemoAppApplication.class.getResource("/doraemon-bundle2-1.0.0-SNAPSHOT-release.zip").getPath();
		System.out.println("bundle1 path is " + bundle1Path);
		System.out.println("bundle2 path is " + bundle2Path);
		RunDoraemonBundle runDoraemonBundle1 = new RunDoraemonBundle(bundle1Path, null);
		runDoraemonBundle1.run();
		runDoraemonBundles.add(runDoraemonBundle1);

		RunDoraemonBundle runDoraemonBundle2 = new RunDoraemonBundle(bundle2Path, null);
		runDoraemonBundle2.run();
		runDoraemonBundles.add(runDoraemonBundle2);

		AsgardClassLoader bundle1ClassLoader = runDoraemonBundle1.getBundle().getBundleClassLoader();
		AsgardClassLoader bundle2ClassLoader = runDoraemonBundle2.getBundle().getBundleClassLoader();
		ClassLoader defaultClassLoader = Thread.currentThread().getContextClassLoader();
		System.out.println(defaultClassLoader);
		System.out.println(bundle1ClassLoader);
		System.out.println(bundle2ClassLoader);

		Thread.currentThread().setContextClassLoader(bundle1ClassLoader);
		runDoraemonBundle1.getBundleBean(DemoFacade.class).doSomething();
	}
}

想咨询一下有哪些可能会导致类似的错误信息?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.