zoukankan      html  css  js  c++  java
  • 一个golang项目笔记 (二) 动态加载库

    这个项目需要用到动态链接库技术, 主程序动态加载一些功能模块,这样在扩充功能时,无须修改主程序,只需要新增功能模块动态调用就可以了。 研究了一下golang官方支持的plugin功能,发现有几点不足。 

         1.官方plugin功能本质上是用cgo实现的,编译一个so文件,然后再调用

         2. 只支持linux, 不支持windows

         3.  plugin模块panic时, 主程序也会panic, 无法做到隔离。

       基于上述原因,我开始另外寻找合适的第三方支持。后来发现这样一个开源库,https://github.com/hashicorp/go-plugin , 感觉符合我的需求。它基于net/rpc ,grpc实现,主程序和plugin程序是两个qtj独立进程,可以通过主程序调用plugin进程启动,也可以附加进程的方式。通过本地网络通讯,达到类似动态链接库调用的效果。 

    官方示例如下:

    plugin:  

    package main
    
    import (
    	"os"
    
    	"github.com/hashicorp/go-hclog"
    	"github.com/hashicorp/go-plugin"
    	"github.com/hashicorp/go-plugin/examples/basic/commons"
    )
    
    // Here is a real implementation of Greeter
    type GreeterHello struct {
    	logger hclog.Logger
    }
    
    func (g *GreeterHello) Greet() string {
    	g.logger.Debug("message from GreeterHello.Greet")
    	return "Hello!"
    }
    
    // handshakeConfigs are used to just do a basic handshake between
    // a plugin and host. If the handshake fails, a user friendly error is shown.
    // This prevents users from executing bad plugins or executing a plugin
    // directory. It is a UX feature, not a security feature.
    var handshakeConfig = plugin.HandshakeConfig{
    	ProtocolVersion:  1,
    	MagicCookieKey:   "BASIC_PLUGIN",
    	MagicCookieValue: "hello",
    }
    
    func main() {
    	logger := hclog.New(&hclog.LoggerOptions{
    		Level:      hclog.Trace,
    		Output:     os.Stderr,
    		JSONFormat: true,
    	})
    
    	greeter := &GreeterHello{
    		logger: logger,
    	}
    	// pluginMap is the map of plugins we can dispense.
    	var pluginMap = map[string]plugin.Plugin{
    		"greeter": &example.GreeterPlugin{Impl: greeter},
    	}
    
    	logger.Debug("message from plugin", "foo", "bar")
    
    	plugin.Serve(&plugin.ServeConfig{
    		HandshakeConfig: handshakeConfig,
    		Plugins:         pluginMap,
    	})
    }
    

      主程序 (调用方):

    package main
    
    import (
    	"fmt"
    	"log"
    	"os"
    	"os/exec"
    
    	hclog "github.com/hashicorp/go-hclog"
    	"github.com/hashicorp/go-plugin"
    	"github.com/hashicorp/go-plugin/examples/basic/commons"
    )
    
    func main() {
    	// Create an hclog.Logger
    	logger := hclog.New(&hclog.LoggerOptions{
    		Name:   "plugin",
    		Output: os.Stdout,
    		Level:  hclog.Debug,
    	})
    
    	// We're a host! Start by launching the plugin process.
    	client := plugin.NewClient(&plugin.ClientConfig{
    		HandshakeConfig: handshakeConfig,
    		Plugins:         pluginMap,
    		Cmd:             exec.Command("./plugin/greeter"),
    		Logger:          logger,
    	})
    	defer client.Kill()
    
    	// Connect via RPC
    	rpcClient, err := client.Client()
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	// Request the plugin
    	raw, err := rpcClient.Dispense("greeter")
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	// We should have a Greeter now! This feels like a normal interface
    	// implementation but is in fact over an RPC connection.
    	greeter := raw.(example.Greeter)
    	fmt.Println(greeter.Greet())
    }
    
    // handshakeConfigs are used to just do a basic handshake between
    // a plugin and host. If the handshake fails, a user friendly error is shown.
    // This prevents users from executing bad plugins or executing a plugin
    // directory. It is a UX feature, not a security feature.
    var handshakeConfig = plugin.HandshakeConfig{
    	ProtocolVersion:  1,
    	MagicCookieKey:   "BASIC_PLUGIN",
    	MagicCookieValue: "hello",
    }
    
    // pluginMap is the map of plugins we can dispense.
    var pluginMap = map[string]plugin.Plugin{
    	"greeter": &example.GreeterPlugin{},
    }
    

      

  • 相关阅读:
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(2)
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(9)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(10)
    CKEditor在asp.net环境下的使用一例
    《Microsoft Sql server 2008 Internals》读书笔记第五章Table(7)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(11)
    千万数据的连续ID表,快速读取其中指定的某1000条数据?
    javascript中的float运算精度
    .Net与Java的互操作(.NET StockTrader微软官方示例应用程序)
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(6)
  • 原文地址:https://www.cnblogs.com/elonlee/p/9499684.html
Copyright © 2011-2022 走看看