This paper mainly analyzes how to use Spring’s observer mode to synchronize gateway configuration data in Soul gateway framework.

background

Dynamic update configuration is the key to ensure high availability of the gateway. The Soul Gateway framework currently supports four synchronization modes: ZooKeeper synchronization, WebSocket synchronization, NACOS synchronization and HTTP long polling synchronization.

Reading the source code for the Soul Gateway framework, you can see that data synchronization is implemented using Spring’s Observer pattern.

An introduction to Spring’s Observer pattern

  • The observer pattern is used when there is a one-to-many relationship between objects. When an object is modified, dependent objects are automatically notified. The observer model belongs to the behavioral model.

  • Refer to Wang Zheng’s analysis of two design patterns used to support extension in the Spring framework. The simple Demo of the Observer pattern in Spring is as follows, mainly consisting of three parts:

    • Defining an inheritanceApplicationEventThe events;
    • Implement an implementationApplicationListenerListeners for interfaces;
    • Define a sender by callingApplicationContextSend events;
    Public class DemoEvent extends ApplicationEvent {private String message; public DemoEvent(Object source, String message) { super(source); } public String getMessage() { return this.message; } @component public class DemoListener implements ApplicationListener<DemoEvent> {@override public void onApplicationEvent(DemoEvent demoEvent) { String message = demoEvent.getMessage(); System.out.println(message); }} // Publisher @Component public class DemoPublisher {@autoWired Private ApplicationContext ApplicationContext; public void publishEvent(DemoEvent demoEvent) { this.applicationContext.publishEvent(demoEvent); }}Copy the code
  • The observer DemoListener is registered in the ApplicationContext when the Spring container is started.

    / / AbstractApplicationContext. Java protected void registerListeners () {/ / send the listener is registered to the event in the for (ApplicationListener <? > listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Get the bean names of all listeners, Registered to the event sender String [] listenerBeanNames = getBeanNamesForType (ApplicationListener. Class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } / /... }Copy the code

Use of the Observer pattern in the Soul framework

  • Soul-admin end uses observer mode in data synchronization, here is a brief analysis of source code implementation;

  • Custom event DataChangedEvent;

    public class DataChangedEvent extends ApplicationEvent {
    //...
    }
    Copy the code
  • Events to monitor and send all by DataChangedEventDispatcher implementation;

    public class DataChangedEventDispatcher implements ApplicationListener<DataChangedEvent>, InitializingBean {
    
        private ApplicationContext applicationContext;
    
        private List<DataChangedListener> listeners;
    }
    Copy the code
  • Soul framework supports different data synchronization strategy, through DataChangedEventDispatcher# onApplicationEvent listener implementation within the method call;

    // DataChangedEventDispatcher.java public void onApplicationEvent(final DataChangedEvent event) { for (DataChangedListener listener : listeners) { switch (event.getGroupKey()) { case APP_AUTH: listener.onAppAuthChanged((List<AppAuthData>) event.getSource(), event.getEventType()); break; case PLUGIN: listener.onPluginChanged((List<PluginData>) event.getSource(), event.getEventType()); break; case RULE: listener.onRuleChanged((List<RuleData>) event.getSource(), event.getEventType()); break; / /... default: throw new IllegalStateException("Unexpected value: " + event.getGroupKey()); }}}Copy the code

  • Each Listner defines its own processing logic according to the data synchronization policy used. For example, using the ZK policy, it mainly involves the creation and deletion of ZK nodes and the writing of node contents.

conclusion

  • With the help ofsoulSource code learning to understand the Spring observer mode, with the observer mode framework, can facilitate the implementation of different data synchronization strategy expansion, here only need to achieve aDataChangedListner You can;

series

  • Soul source learning [1] – preliminary exploration
  • Soul source learning [2] – divide load balancing plug-in
  • Soul source learning [3] – Dubbo plug-in
  • Soul source learning [4] – RateLimiter stream limiting plug-in
  • Soul source learning [5] – SpringCloud plug-in
  • Soul source learning [6] – Chain of responsibility mode
  • Soul source learning [7] – Data synchronization strategy websocket synchronization
  • [8] – Data synchronization strategy for ZooKeeper synchronization
  • [9] – ZooKeeper Synchronization (2)