Server architecture with plugins

agolangf · · 18 次点击    
<p>I don&#39;t have a good reason or name for this, just want to check with the go crowd and see if it&#39;s the worst possible idea. The motivation behind the idea is to have a dynamic-ish server. </p> <p>When the server starts it loads everything in a plugins folder. A plugin will be require the following functions to be defined to be registered:</p> <ul> <li>RouteName () string</li> <li>Handle (response writer, request, []string args) - allows plugin to be registered in the handler for web requests</li> <li>HandleIC (interface{}) interface{} - allows plugin to be registered in the handler for <em>internal calls</em></li> <li>Receive (interface{})</li> </ul> <h1></h1> <p>There are 2 global maps. A map for web handlers and a map for internal handlers. When a plugin has all of the required parts, it will be added to both maps at map[RouteName]function. Each plugin has its Receive function invoked, and a method from the core server is passed in. This method is passed to every plugin and allows them to <em>internal invoke</em> another plugin via HandleIC. The plugins are organized as such...</p> <ul> <li>main.go - logic for this <em>module</em> to handle</li> <li>web.go - where Handle is defined, gets vars from web request and then calls a function from main.go</li> <li>internal.go - where HandleIC is defined, gets vars from an interface{} passed from another plugin</li> </ul> <h1></h1> <p>Here is a simple use case for this setup...</p> <ul> <li>user posts credentials to /auth/login on main site</li> <li>the server core sends [&#34;login&#34;] to HandlerMap[&#34;auth&#34;]function(...) along with the request and response writer</li> <li>the auth plugin does some switch / condition and determines what to do for &#34;login&#34;</li> <li>the auth plugin uses the function it received from Receive and sends an internal call to &#34;db&#34; with args map[string]string{ &#34;action&#34; : &#34;login&#34;, &#34;user&#34;: &#34;username&#34;, &#34;pass&#34;: &#34;password&#34; }</li> <li>the core invokes the db plugin&#39;s HandleIC with the given args</li> <li>the db plugin tries to fetch rows from an SQL server with the given input and returns them to the auth plugin</li> <li>the auth plugin determines if authentication was successful and has a response writer to let the user know</li> </ul> <p>The benefit (I imagine) is that only the db plugin needs to deal with the database instead of every plugin having to import sql drivers and create connections to the db. It&#39;s a separation of concerns implemented as plugins that have means of sending [primarily] map[string]string requests to each other without any additional network activity. Not every class will need Handle (db probably doesn&#39;t need to deal with user web requests directly) and not every class will need an internal call handler (can&#39;t think of a good example that exclusively handles web requests and isn&#39;t used by another plugin - maybe serving files?).</p> <h1></h1> <p>I just want to make sure the receive / internal calls passing through the main server isn&#39;t the worst idea ever conceived. I thought an alternative could be each plugin specifies a list of plugins it needs access to and then each plugin gets its own map[string]function for internal calls directly instead of passing args and results around through the main file. I want to confirm the overhead / performance hits involved are negligible, either from a GO expert or someone very familiar with SO files. Please tell me if it&#39;s a horrible idea to have them communicating like this. </p> <hr/>**评论:**<br/><br/>65a: <pre><p>What problem are you trying to solve?<br/> Why not use strong typing instead of interface{}?<br/> Why do you need plugins at all? </p></pre>Tomnnn: <pre><blockquote> <p>What problem are you trying to solve?</p> </blockquote> <p>Organization, I guess. Something that could serve as a base in any project. </p> <h1></h1> <blockquote> <p>Why not use strong typing instead of interface{}?</p> </blockquote> <p>I was thinking that <em>most</em> of these exchanges are going to be map[string]string but the returns are going to vary a lot so I&#39;d want each class to type assert what it&#39;s expecting. A sort-of answer to all 3 of those questions is that I&#39;d like to be able to interface multiple applications that may previously have been isolated.</p> <h1></h1> <blockquote> <p>Why do you need plugins at all?</p> </blockquote> <p>Lazyiness: think about all of the boilerplate I don&#39;t have to write over time by having a folder of plugins and each plugin has some kind of pseudo-interface that is enforced with the load. And there&#39;s no linkage or other alteration, a plugin simply needs to send some args and the name of another plugin to the main class and it&#39;ll just work. Over time, some plugins might be entire applications. I like the option of being able to integrate that application into the server base just by building it as a plugin and adding those <em>interface</em> methods. </p> <h1></h1> <p>I just left a job with 30k+ line files of source code and literally over 100 lines of <em>import</em> lines. I&#39;d like to avoid that. I know direct invocation is going to be way faster / better than the function overhead and map[string]function calls, but idk. It&#39;d be nice if this wasn&#39;t a horrible idea. </p></pre>
18 次点击  
加入收藏 微博
0 回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传