trpc.group/trpc-go/trpc-go@v1.0.3/plugin/README.md (about) 1 English | [中文](README.zh_CN.md) 2 3 # Plugin 4 5 tRPC-Go is designed with a plugin architecture concept, which allows the framework to connect with various ecosystems through plugins, providing openness and extensibility. 6 The plugin package is used to manage plugins that need to be loaded based on configurations. 7 Plugins that do not rely on configuration are relatively simple, such as [codec plugins](/codec/README.md), which will not be discussed here. 8 Therefore, we will first introduce the design of the plugin package and then explain how to develop a plugin that needs to be loaded based on configuration. 9 10 ## Design of the `plugin` package 11 12 The plugin package manages all plugins through a "plugin factory". 13 Each plugin needs to be registered with the plugin factory. 14 The plugin factory adopts a two-level management mode: 15 The first level is the plugin type, such as log type, conf type, selector type, etc. 16 The second level is the plugin name, such as local file configuration, remote file configuration, local database configuration, etc. for conf plugins. 17 18 ```ascii 19 +-----------------+ 20 +---+ Plugin Factory +----+ 21 | +--------+--------+ | 22 | | | 23 +---v--+ +--v--+ +----v-----+ 24 +---------+ conf | | log | | selector | 25 | +---+--+ +-----+ +----+-----+ 26 | | | 27 +----v-----+ +-----v-------+ +----v----+ 28 |local-file| | remote-file | ...... | polaris | 29 +----------+ +-------------+ +---------+ 30 ``` 31 32 For the plugin type, the `plugin` package does not impose any restrictions, and you can add your own plugin types. 33 34 ### Common plugin types 35 36 According to their functions, the framework provides the following five types of common plugins: 37 38 - Configuration: Provides a standard interface for obtaining configurations, getting configuration data from various data sources such as local files, configuration centers, etc., providing configuration parsing in multiple formats such as json, yaml, etc., and the framework also provides a watch mechanism to achieve dynamic updates of configurations. 39 - Logging: Provides a unified logging print and log reporting standard interface. Log plugins can complete the docking with remote log systems by implementing the log reporting interface. 40 - Protocol: Provides standard interfaces related to protocol encoding and decoding, allowing the expansion of business protocols, serialization types, data compression methods, and other protocol processing through plugins. 41 - Name Service: Provides standard interfaces including service registration, service discovery, policy routing, load balancing, and fusing, used to implement service routing addressing. 42 - Filter: Provides a generic filter interface, allowing users to set up buried points in the context of service calls to implement functions such as module monitoring, cross-cutting logging, link tracking, and overload protection. 43 44 ## How to develop a plugin that needs to be loaded based on configuration 45 46 Developing a plugin that needs to be loaded based on configuration usually involves implementing the plugin and configuring the plugin. [A runnable specific example](/examples/features/plugin) 47 48 ### Implementing the plugin 49 50 1. The plugin implements the `plugin.Factory` interface. 51 52 ```go 53 // Factory is a unified abstract for the plugin factory. External plugins need to implement this interface to generate specific plugins and register them in specific plugin types. 54 type Factory interface { 55 // Type is the type of the plugin, such as selector, log, config, tracing. 56 Type() string 57 // Setup loads the plugin based on the configuration node. Users need to define the specific plugin configuration data structure first. 58 Setup(name string, configDec Decoder) error 59 } 60 ``` 61 62 2. The plugin calls `plugin.Register` to register itself with the `plugin` package. 63 64 ```go 65 // Register registers the plugin factory. You can specify the plugin name yourself, and different factory instances can be registered for the same implementation with different configurations. 66 func Register(name string, p Factory) 67 ``` 68 69 ### Configuring the plugin 70 71 1. Import the plugin's package in the `main` package. 72 2. Configure the plugin under the `plugins` field in the configuration file. The configuration file format is: 73 ```yaml 74 # Plugin configuration 75 plugins: 76 # Plugin type 77 log: 78 # Plugin name 79 logger1: 80 # Plugin detailed configuration, please refer to the instructions of each plugin for details 81 .... 82 logger2: 83 # Plugin detailed configuration, please refer to the instructions of each plugin for details 84 .... 85 # Plugin type 86 config: 87 # Plugin name 88 rainbow: 89 # Plugin detailed configuration, please refer to the instructions of each plugin for details 90 .... 91 tconf: 92 # Plugin detailed configuration, please refer to the instructions of each plugin for details 93 .... 94 ``` 95 The above configuration defines two plugin types and four plugins. 96 There are logger1 and logger2 plugins under the log type. 97 There are local-file and remote-file plugins under the config type. 98 99 ### Plugin initialization order 100 101 After the tRPC-GO server calls the `trpc.NewServer()` function, it reads all plugin configurations under the "plugins" field in the framework configuration file and then calls the "Setup()" function of each plugin to complete the initialization of the plugin configuration. 102 In general, plugins are independent of each other, and the framework initializes the plugins in a random order (e.g., plugin A depends on plugin B). 103 If a plugin depends on other plugins, it can implement the following methods to declare the dependency relationship. 104 105 ```go 106 // Depender is the interface for "Strong Dependence". 107 // If plugin a "Strongly" depends on plugin b, b must exist and 108 // a will be initialized after b's initialization. 109 type Depender interface { 110 // DependsOn returns a list of plugins that are relied upon. 111 // The list elements are in the format of "type-name" like [ "selector-polaris" ]. 112 DependsOn() []string 113 } 114 115 // FlexDepender is the interface for "Weak Dependence". 116 // If plugin a "Weakly" depends on plugin b and b does exist, 117 // a will be initialized after b's initialization. 118 type FlexDepender interface { 119 FlexDependsOn() []string 120 } 121 ``` 122 123 The dependency relationship is divided into strong dependency and weak dependency. 124 Strong dependency requires the depended plugin to exist, otherwise, the framework will panic. 125 Weak dependency will not panic. 126 The framework will first ensure that all strong dependencies are satisfied, and then check the weak dependencies. 127 128 For example, in the following example, the plugin initialization strongly depends on the selector type plugin a and weakly depends on the config type plugin b. 129 130 ```go 131 func (p *Plugin) DependsOn() []string { 132 return []string{"selector-a"} 133 } 134 func (p *Plugin) FlexDependsOn() []string { 135 return []string{"config-b"} 136 } 137 ```