第三篇:Nacos 源码搭建

  • Post author:
  • Post category:其他


上一篇已经介绍了Nacos的基础知识(

传送门

),也从源码启动了Nacos Server,今天我们探究下项目结构,以便于搭建自己的服务端!


我们先看下源码中Nacos-console 项目的结构:

目录包含了config(配置)、controller(控制层)、exception(自定义异常)、filter(过滤器)、model、security.nacos(安全模块)、utils(工具类),定义习惯也是通用定义,可以从目录结构、类名称直接认识到其实现的功能。下面介绍几个核心文件:


  1. config目录下的ConsoleConfig.java:

@Component@EnableScheduling@PropertySource("/application.properties")public class ConsoleConfig {    @Autowired    private ControllerMethodsCache methodsCache;    @PostConstruct    public void init() {        methodsCache.initClassMethod("com.alibaba.nacos.naming.controllers");        methodsCache.initClassMethod("com.alibaba.nacos.console.controller");        methodsCache.initClassMethod("com.alibaba.nacos.config.server.controller");    }    @Bean    public CorsFilter corsFilter() {        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();        CorsConfiguration config = new CorsConfiguration();        config.setAllowCredentials(true);        config.addAllowedOrigin("*");        config.addAllowedHeader("*");        config.setMaxAge(18000L);        config.addAllowedMethod("*");        source.registerCorsConfiguration("/**", config);        return new CorsFilter(source);    }}

关于注解的解释,请移步:Spring 相关注解说明(关注公众号,打开菜单)

这里主要实现了两个方法,init()和corsFilter()

init():主要利用反射的方法初始化了相关类,initClassMethod的实现:

   public void initClassMethod(String packageName) {        Reflections reflections = new Reflections(packageName);        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(RequestMapping.class);
        for (Class clazz : classesList) {            initClassMethod(clazz);        }    }

corsFilter():主要为了解决跨域问题,它允许浏览器向跨域服务器发送Ajax请求,打破了Ajax只能访问本站内的资源限制。分布式微服务架构这几乎是一定会遇到的问题。


2.controller目录下的控制器:

HealthController:主要是健康检查、节点检查,具体在那个功能生效,后续再进行说明

NamespaceController:命名空间管理
PermissionController:权限认证
RoleController:角色管理

ServerStateController:节点信息

UserController:用户管理,包含登陆等

这里代码不在详细说明,


3.filter目录下


JwtAuthenticationTokenFilter:

主要功能校验令牌是否有效

@Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        String jwt = resolveToken(request);
        if (StringUtils.isNotBlank(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) {
            this.tokenManager.validateToken(jwt);
            Authentication authentication = this.tokenManager.getAuthentication(jwt);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        chain.doFilter(request, response);
    }
    /**
     * Get token from header
     */
    private String resolveToken(HttpServletRequest request) {
        String bearerToken = request.getHeader(NacosAuthConfig.AUTHORIZATION_HEADER);
        if (StringUtils.isNotBlank(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
            return bearerToken.substring(7);
        }
        String jwt = request.getParameter(Constants.ACCESS_TOKEN);
        if (StringUtils.isNotBlank(jwt)) {
            return jwt;
        }
        return null;
    }


4.security.nacos

主要包含一些具体的实现类,比如用户登录的逻辑(NacosAuthManager),令牌校验和生成的逻辑(JwtTokenManager)


配置本地数据库启动



Nacos 本身在单机模式时nacos使用嵌入式数据库实现数据的存储,在0.7版本增加了支持mysql数据源能力,具体步骤是:

  • 1.安装数据库,版本要求:5.6.5+(之前已安装了一主二从数据库)

  • 2.初始化mysql数据库,数据库初始化文件:nacos-mysql.sql

  • 3.修改conf/application.properties文件,增加支持mysql数据源配置(目前只支持mysql),添加mysql数据源的url、用户名和密码。


spring.datasource.platform=mysql
db.num=3
db.user=root
db.password=123456
db.url.0=jdbc:mysql://192.168.65.129:3000/nacos_config?serverTimezone=GMT%2B8&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.url.1=jdbc:mysql://192.168.65.129:3001/nacos_config?serverTimezone=GMT%2B8&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.url.2=jdbc:mysql://192.168.65.129:3002/nacos_config?serverTimezone=GMT%2B8&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true

配置完毕,启动Nacos.java  即可。


Connected to the target VM, address: '127.0.0.1:50380', transport: 'socket'

         ,--.
       ,--.'|
   ,--,:  : |                                           Nacos 
,`--.'`|  ' :                       ,---.               Running in stand alone mode, All function modules
|   :  :  | |                      '   ,'\   .--.--.    Port: 8848
:   |   \ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: 21524
|   : '  '; | /       \   /     \.   ; ,. :|  :  /`./   Console: http://192.168.19.1:8848/nacos/index.html
'   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_
|   | | \   | \__\/: . ..    ' / '   | .; : \  \    `.      https://nacos.io
'   : |  ; .' ," .--.; |'   ; :__|   :    |  `----.   \
|   | '`--'  /  /  ,.  |'   | '.'|\   \  /  /  /`--'  /
'   : |     ;  :   .'   \   :    : `----'  '--'.     /
;   |.'     |  ,     .-./\   \  /            `--'---'
'---'        `--`---'     `----'

2020-04-21 23:54:23.186  INFO 21524 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration' of type [org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration$$EnhancerBySpringCGLIB$$f3ad21c2] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-21 23:54:23.310  INFO 21524 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'objectPostProcessor' of type [org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-21 23:54:23.314  INFO 21524 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler@30f28b5' of type [org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-21 23:54:23.315  INFO 21524 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration' of type [org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration$$EnhancerBySpringCGLIB$$1881c474] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-21 23:54:23.322  INFO 21524 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'methodSecurityMetadataSource' of type [org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-21 23:54:24.281  INFO 21524 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8848 (http)
2020-04-21 23:54:24.449  INFO 21524 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3450 ms
2020-04-21 23:54:31.734  INFO 21524 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-04-21 23:54:31.930  INFO 21524 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page: class path resource [static/index.html]
2020-04-21 23:54:32.513  INFO 21524 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: Ant [pattern='/**'], []
2020-04-21 23:54:32.546  INFO 21524 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@3b17759c, org.springframework.security.web.context.SecurityContextPersistenceFilter@6956eb58, org.springframework.security.web.header.HeaderWriterFilter@52fe87e0, org.springframework.security.web.csrf.CsrfFilter@458b4487, org.springframework.security.web.authentication.logout.LogoutFilter@153d14e3, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@6127ef86, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@301f9aa0, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@11cdf948, org.springframework.security.web.session.SessionManagementFilter@4d3a7f83, org.springframework.security.web.access.ExceptionTranslationFilter@73818435]
2020-04-21 23:54:32.638  INFO 21524 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 2 endpoint(s) beneath base path '/actuator'
2020-04-21 23:54:32.670  INFO 21524 --- [           main] o.s.s.c.ThreadPoolTaskScheduler          : Initializing ExecutorService 'taskScheduler'
2020-04-21 23:54:32.781  INFO 21524 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8848 (http) with context path '/nacos'
2020-04-21 23:54:32.790  INFO 21524 --- [           main] c.l.StartingSpringApplicationRunListener : Nacos logs files: C:\Users\back_\nacos\logs\
2020-04-21 23:54:32.790  INFO 21524 --- [           main] c.l.StartingSpringApplicationRunListener : Nacos conf files: C:\Users\back_\nacos\conf\
2020-04-21 23:54:32.790  INFO 21524 --- [           main] c.l.StartingSpringApplicationRunListener : Nacos data files: C:\Users\back_\nacos\data\
2020-04-21 23:54:32.790  INFO 21524 --- [           main] c.l.StartingSpringApplicationRunListener : Nacos started successfully in stand alone mode.
2020-04-21 23:54:32.913  INFO 21524 --- [nio-8848-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-04-21 23:54:32.923  INFO 21524 --- [nio-8848-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 10 ms

访问:http://localhost:8848/nacos/,登录账户/密码:nacos/nacos

随意添加配置,

这时,我们的数据库config_info表中已经添加了这条记录

从库也同步更新


搭建自己的NacosServer

创建新的SpringBoot项目:


项目创建完成后

为了方便测创建试,这里先把功能性代码直接复制到新项目,并解决引入问题

目的是先完成项目启动,并在解决引入问题过程中,熟悉项目依赖和项目结构,以及功能。

把Nacos-console 项目中以下目录完整复制到我们的项目中,

com/alibaba/nacos/console

console/src/main/resources/META-INF

console/src/main/resources/static

整理过的pom.xml 配置:

<properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>7.0.59</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-config</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-naming</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-core</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.10.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.10.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.10.5</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <profiles>
        <profile>
            <id>release-nacos</id>
            <build>
                <finalName>nacos-server</finalName>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <version>2.1.1.RELEASE</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>repackage</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>
 

在启动类上添加扫描注解:


@ComponentScan("com.reims.main,com.alibaba.nacos")
@SpringBootApplication
public class NacosServerApplication {

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

}
 

设置启动单机模式:

在application.properties中添加mysql数据源:

spring.datasource.platform=mysql
db.num=3
db.user=root
db.password=123456
db.url.0=jdbc:mysql://192.168.65.129:3000/nacos_config?serverTimezone=GMT%2B8&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.url.1=jdbc:mysql://192.168.65.129:3001/nacos_config?serverTimezone=GMT%2B8&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.url.2=jdbc:mysql://192.168.65.129:3002/nacos_config?serverTimezone=GMT%2B8&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true

切记,在resources目录下的nacos-default.properties一定要复制过来,因为这里面包含着Nacoe server 核心程序Nacos Config 的默认配置,比如:


useAddressServer=true
# whether open interInterFaceFilter; true:open; false:close; if open, others can't call inner interface. default:false
openInnerInterfaceFilter=false
# quickStart  stip dumpAll;only dump change config
isQuickStart=false
# server notify each otherd
notifyConnectTimeout=200
# server notify each other
notifySocketTimeout=8000
# whether health check
isHealthCheck=true
# health check max fail count
maxHealthCheckFailCount=12
 

下节我们将全部自主搭建的时候再来讲解这个文件的内容,以及怎么去掉这个文件。

此时启动NacosServerApplication,


Connected to the target VM, address: '127.0.0.1:52415', transport: 'socket'

         ,--.
       ,--.'|
   ,--,:  : |                                           Nacos 
,`--.'`|  ' :                       ,---.               Running in stand alone mode, All function modules
|   :  :  | |                      '   ,'\   .--.--.    Port: 8848
:   |   \ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: 18280
|   : '  '; | /       \   /     \.   ; ,. :|  :  /`./   Console: http://192.168.19.1:8848/nacos/index.html
'   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_
|   | | \   | \__\/: . ..    ' / '   | .; : \  \    `.      https://nacos.io
'   : |  ; .' ," .--.; |'   ; :__|   :    |  `----.   \
|   | '`--'  /  /  ,.  |'   | '.'|\   \  /  /  /`--'  /
'   : |     ;  :   .'   \   :    : `----'  '--'.     /
;   |.'     |  ,     .-./\   \  /            `--'---'
'---'        `--`---'     `----'

2020-04-23 00:00:56.606  INFO 18280 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration' of type [org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-23 00:00:56.717  INFO 18280 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'objectPostProcessor' of type [org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-23 00:00:56.719  INFO 18280 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler@2c0c4c0a' of type [org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-23 00:00:56.720  INFO 18280 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration' of type [org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-23 00:00:56.724  INFO 18280 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'methodSecurityMetadataSource' of type [org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-04-23 00:00:57.606  INFO 18280 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8848 (http)
2020-04-23 00:00:57.717  INFO 18280 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2908 ms
2020-04-23 00:01:04.717  INFO 18280 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-04-23 00:01:04.823  INFO 18280 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page: class path resource [static/index.html]
2020-04-23 00:01:05.087  INFO 18280 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: Ant [pattern='/**'], []
2020-04-23 00:01:05.121  INFO 18280 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@189e96af, org.springframework.security.web.context.SecurityContextPersistenceFilter@e3692ca, org.springframework.security.web.header.HeaderWriterFilter@3791af, org.springframework.security.web.csrf.CsrfFilter@578d5d02, org.springframework.security.web.authentication.logout.LogoutFilter@78bce1c4, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@5cfe28e1, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@15ee8861, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@45b6c666, org.springframework.security.web.session.SessionManagementFilter@5535e9, org.springframework.security.web.access.ExceptionTranslationFilter@397dfbe8]
2020-04-23 00:01:05.140  INFO 18280 --- [           main] o.s.s.c.ThreadPoolTaskScheduler          : Initializing ExecutorService 'taskScheduler'
2020-04-23 00:01:05.148  INFO 18280 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 2 endpoint(s) beneath base path '/actuator'
2020-04-23 00:01:05.238  INFO 18280 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8848 (http) with context path '/nacos'
2020-04-23 00:01:05.244  INFO 18280 --- [           main] c.l.StartingSpringApplicationRunListener : Nacos logs files: C:\Users\back_\nacos\logs\
2020-04-23 00:01:05.244  INFO 18280 --- [           main] c.l.StartingSpringApplicationRunListener : Nacos conf files: C:\Users\back_\nacos\conf\
2020-04-23 00:01:05.244  INFO 18280 --- [           main] c.l.StartingSpringApplicationRunListener : Nacos data files: C:\Users\back_\nacos\data\
2020-04-23 00:01:05.245  INFO 18280 --- [           main] c.l.StartingSpringApplicationRunListener : Nacos started successfully in stand alone mode.
2020-04-23 00:01:05.590  INFO 18280 --- [nio-8848-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-04-23 00:01:05.598  INFO 18280 --- [nio-8848-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 8 ms
 

访问:http://localhost:8848/nacos/,使用nacos/nacos 登录,即可看到系统界面

结论:本章从简单解析Nacos console 样例工程,并仿照搭建了自己的Nacos Server,但是现在的逻辑都是基于原始样例,不过本章的目的也不在于直接了解源码写法,而是从使用的角度,先入门,在使用的过程中去深入的了解每个模块之间的结构和实现,了解更深的技术点。达到学得会,也能用自己的角度解释出来。这也是我的观念,先会用,有了场景再去深入,远远比干巴巴的一对技术原理要实用的多,并不是每个人都是技术专家,都能成为技术专家。只有在更多的使用中发现更多的问题,丰富的解决问题的经验也将会是你的财富。

这一章,我从对Nacos源码零了解写出来,中间也遇到了不少问题,就那个切记提到的配置文件,就让我疑惑了好久。不够一个一个问题解决下来,现在我们对整个依赖的机构至少有了个初步的理解不是么?也成功的从整个Nacos-all 体系代码中,单独分离出来了服务端。这样我们以后不管是搭建自己的服务端,还是扩展前端的管理能力,我们对结构都有清晰的认识,怎么做也就有了自己的想法。比如构建自己的前台管理页面融入到现有的管理系统,纯后端做微服务集群来管理,等等。

所以,包括以后,我的文章应该不会直接讲一大堆的技术原理,除非有必要,我一般都会从认知的角度来出发,目的是从知道、了解到达会用,能说的出来,有自己的想法和逻辑。最后达到自己的一套常用的体系架构。并能随意剪切调整,以便应对各种业务情况!

↓扫码关注不迷路,更多操作持续更新中↓

↓扫码关注,优惠先享↓



版权声明:本文为Space_Life原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。