第三篇:Nacos 源碼搭建

  上一篇已經介紹了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 體系代碼中,單獨分離出來了服務端。這樣我們以後不管是搭建自己的服務端,還是擴展前端的管理能力,我們對結構都有清晰的認識,怎麼做也就有了自己的想法。比如構建自己的前臺管理頁面融入到現有的管理系統,純後端做微服務集羣來管理,等等。

        所以,包括以後,我的文章應該不會直接講一大堆的技術原理,除非有必要,我一般都會從認知的角度來出發,目的是從知道、瞭解到達會用,能說的出來,有自己的想法和邏輯。最後達到自己的一套常用的體系架構。並能隨意剪切調整,以便應對各種業務情況!

↓掃碼關注不迷路,更多操作持續更新中↓

↓掃碼關注,優惠先享↓

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章