diff --git a/config_center/apollo/impl.go b/config_center/apollo/impl.go
index 4dc19817846fe5c9c0552738f2058a15d20efabc..d9c9ad2c301810148a0931c3667bc20d11ead822 100644
--- a/config_center/apollo/impl.go
+++ b/config_center/apollo/impl.go
@@ -128,6 +128,12 @@ func (c *apolloConfiguration) GetRule(key string, opts ...cc.Option) (string, er
 	return c.GetInternalProperty(key, opts...)
 }
 
+// PublishConfig will publish the config with the (key, group, value) pair
+func (c *apolloConfiguration) PublishConfig(string, string, string) error {
+	// todo(@zouyx)
+	return nil
+}
+
 func (c *apolloConfiguration) GetProperties(key string, opts ...cc.Option) (string, error) {
 	/**
 	 * when group is not null, we are getting startup configs(config file) from Config Center, for example:
diff --git a/config_center/dynamic_configuration.go b/config_center/dynamic_configuration.go
index d6c3b06b327f16c709b09121e589db6694d3663e..e5284e89eb5bfade76378975338069de649dfcbb 100644
--- a/config_center/dynamic_configuration.go
+++ b/config_center/dynamic_configuration.go
@@ -50,6 +50,10 @@ type DynamicConfiguration interface {
 
 	//GetInternalProperty get value by key in Default properties file(dubbo.properties)
 	GetInternalProperty(string, ...Option) (string, error)
+
+	// PublishConfig will publish the config with the (key, group, value) pair
+	PublishConfig(string, string, string) error
+	
 }
 
 // Options ...
diff --git a/config_center/mock_dynamic_config.go b/config_center/mock_dynamic_config.go
index 4d972b629abb7abd7cc0d0018026e4ccc04a1e4f..9f5bbe934c2a7c2a8a30ba42d024cacedc92d084 100644
--- a/config_center/mock_dynamic_config.go
+++ b/config_center/mock_dynamic_config.go
@@ -81,6 +81,10 @@ func (f *MockDynamicConfigurationFactory) GetDynamicConfiguration(_ *common.URL)
 
 }
 
+func (c *MockDynamicConfiguration) PublishConfig(string, string, string) error {
+	return nil
+}
+
 // MockDynamicConfiguration ...
 type MockDynamicConfiguration struct {
 	parser   parser.ConfigurationParser
diff --git a/config_center/nacos/impl.go b/config_center/nacos/impl.go
index 60ab89b003ff62016b9137223425c1051356975f..a1f9ff8cc65476ac6eb3381e01f8c0a43a3d8c68 100644
--- a/config_center/nacos/impl.go
+++ b/config_center/nacos/impl.go
@@ -18,6 +18,8 @@
 package nacos
 
 import (
+	"errors"
+	"strings"
 	"sync"
 )
 
@@ -65,101 +67,130 @@ func newNacosDynamicConfiguration(url *common.URL) (*nacosDynamicConfiguration,
 }
 
 // AddListener Add listener
-func (n *nacosDynamicConfiguration) AddListener(key string, listener config_center.ConfigurationListener, opions ...config_center.Option) {
-	n.addListener(key, listener)
+func (nacos *nacosDynamicConfiguration) AddListener(key string, listener config_center.ConfigurationListener, opions ...config_center.Option) {
+	nacos.addListener(key, listener)
 }
 
 // RemoveListener Remove listener
-func (n *nacosDynamicConfiguration) RemoveListener(key string, listener config_center.ConfigurationListener, opions ...config_center.Option) {
-	n.removeListener(key, listener)
+func (nacos *nacosDynamicConfiguration) RemoveListener(key string, listener config_center.ConfigurationListener, opions ...config_center.Option) {
+	nacos.removeListener(key, listener)
 }
 
-//nacos distinguishes configuration files based on group and dataId. defalut group = "dubbo" and dataId = key
-func (n *nacosDynamicConfiguration) GetProperties(key string, opts ...config_center.Option) (string, error) {
-	return n.GetRule(key, opts...)
+// GetProperties nacos distinguishes configuration files based on group and dataId. defalut group = "dubbo" and dataId = key
+func (nacos *nacosDynamicConfiguration) GetProperties(key string, opts ...config_center.Option) (string, error) {
+	return nacos.GetRule(key, opts...)
 }
 
 // GetInternalProperty Get properties value by key
-func (n *nacosDynamicConfiguration) GetInternalProperty(key string, opts ...config_center.Option) (string, error) {
-	return n.GetProperties(key, opts...)
+func (nacos *nacosDynamicConfiguration) GetInternalProperty(key string, opts ...config_center.Option) (string, error) {
+	return nacos.GetProperties(key, opts...)
+}
+
+// PublishConfig will publish the config with the (key, group, value) pair
+func (nacos *nacosDynamicConfiguration) PublishConfig(key string, group string, value string) error {
+
+	group = nacos.resolvedGroup(group)
+
+	ok, err := (*nacos.client.Client()).PublishConfig(vo.ConfigParam{
+		DataId:   key,
+		Group:    group,
+		Content:  value,
+	})
+
+	if err != nil {
+		return err
+	}
+	if !ok {
+		return errors.New("publish config to Nocos failed")
+	}
+	return nil
 }
 
 // GetRule Get router rule
-func (n *nacosDynamicConfiguration) GetRule(key string, opts ...config_center.Option) (string, error) {
+func (nacos *nacosDynamicConfiguration) GetRule(key string, opts ...config_center.Option) (string, error) {
 	tmpOpts := &config_center.Options{}
 	for _, opt := range opts {
 		opt(tmpOpts)
 	}
-	content, err := (*n.client.Client()).GetConfig(vo.ConfigParam{
+	content, err := (*nacos.client.Client()).GetConfig(vo.ConfigParam{
 		DataId: key,
-		Group:  tmpOpts.Group,
+		Group:  nacos.resolvedGroup(tmpOpts.Group),
 	})
 	if err != nil {
 		return "", perrors.WithStack(err)
 	} else {
-		return string(content), nil
+		return content, nil
 	}
 }
 
 // Parser Get Parser
-func (n *nacosDynamicConfiguration) Parser() parser.ConfigurationParser {
-	return n.parser
+func (nacos *nacosDynamicConfiguration) Parser() parser.ConfigurationParser {
+	return nacos.parser
 }
 
 // SetParser Set Parser
-func (n *nacosDynamicConfiguration) SetParser(p parser.ConfigurationParser) {
-	n.parser = p
+func (nacos *nacosDynamicConfiguration) SetParser(p parser.ConfigurationParser) {
+	nacos.parser = p
 }
 
 // NacosClient Get Nacos Client
-func (n *nacosDynamicConfiguration) NacosClient() *NacosClient {
-	return n.client
+func (nacos *nacosDynamicConfiguration) NacosClient() *NacosClient {
+	return nacos.client
 }
 
 // SetNacosClient Set Nacos Client
-func (n *nacosDynamicConfiguration) SetNacosClient(client *NacosClient) {
-	n.cltLock.Lock()
-	n.client = client
-	n.cltLock.Unlock()
+func (nacos *nacosDynamicConfiguration) SetNacosClient(client *NacosClient) {
+	nacos.cltLock.Lock()
+	nacos.client = client
+	nacos.cltLock.Unlock()
 }
 
 // WaitGroup for wait group control, zk client listener & zk client container
-func (n *nacosDynamicConfiguration) WaitGroup() *sync.WaitGroup {
-	return &n.wg
+func (nacos *nacosDynamicConfiguration) WaitGroup() *sync.WaitGroup {
+	return &nacos.wg
 }
 
 // GetDone For nacos client control	RestartCallBack() bool
-func (n *nacosDynamicConfiguration) GetDone() chan struct{} {
-	return n.done
+func (nacos *nacosDynamicConfiguration) GetDone() chan struct{} {
+	return nacos.done
 }
 
 // GetUrl Get Url
-func (n *nacosDynamicConfiguration) GetUrl() common.URL {
-	return *n.url
+func (nacos *nacosDynamicConfiguration) GetUrl() common.URL {
+	return *nacos.url
 }
 
 // Destroy Destroy configuration instance
-func (n *nacosDynamicConfiguration) Destroy() {
-	close(n.done)
-	n.wg.Wait()
-	n.closeConfigs()
+func (nacos *nacosDynamicConfiguration) Destroy() {
+	close(nacos.done)
+	nacos.wg.Wait()
+	nacos.closeConfigs()
+}
+
+// resolvedGroup will regular the group. Now, it will replace the '/' with '-'.
+// '/' is a special character for nacos
+func (nacos *nacosDynamicConfiguration) resolvedGroup(group string) string {
+	if len(group) <=0 {
+		return group
+	}
+	return strings.ReplaceAll(group, "/", "-")
 }
 
 // IsAvailable Get available status
-func (n *nacosDynamicConfiguration) IsAvailable() bool {
+func (nacos *nacosDynamicConfiguration) IsAvailable() bool {
 	select {
-	case <-n.done:
+	case <-nacos.done:
 		return false
 	default:
 		return true
 	}
 }
 
-func (r *nacosDynamicConfiguration) closeConfigs() {
-	r.cltLock.Lock()
-	client := r.client
-	r.client = nil
-	r.cltLock.Unlock()
+func (nacos *nacosDynamicConfiguration) closeConfigs() {
+	nacos.cltLock.Lock()
+	client := nacos.client
+	nacos.client = nil
+	nacos.cltLock.Unlock()
 	// Close the old client first to close the tmp node
 	client.Close()
 	logger.Infof("begin to close provider nacos client")
diff --git a/config_center/nacos/impl_test.go b/config_center/nacos/impl_test.go
index b4e6f1d0259979eba28dd81e8f480ab4ae03a39f..4032c91cda512b649140db6eea3dc11eeb482f27 100644
--- a/config_center/nacos/impl_test.go
+++ b/config_center/nacos/impl_test.go
@@ -60,12 +60,7 @@ func runMockConfigServer(configHandler func(http.ResponseWriter, *http.Request),
 
 func mockCommonNacosServer() *httptest.Server {
 	return runMockConfigServer(func(writer http.ResponseWriter, request *http.Request) {
-		data := `
-	dubbo.service.com.ikurento.user.UserProvider.cluster=failback
-	dubbo.service.com.ikurento.user.UserProvider.protocol=myDubbo1
-	dubbo.protocols.myDubbo.port=20000
-	dubbo.protocols.myDubbo.name=dubbo
-`
+		data := "true"
 		fmt.Fprintf(writer, "%s", data)
 	}, func(writer http.ResponseWriter, request *http.Request) {
 		data := `dubbo.properties%02dubbo%02dubbo.service.com.ikurento.user.UserProvider.cluster=failback`
@@ -93,6 +88,16 @@ func Test_GetConfig(t *testing.T) {
 	assert.NoError(t, err)
 }
 
+func TestNacosDynamicConfiguration_PublishConfig(t *testing.T) {
+	nacos, err := initNacosData(t)
+	assert.Nil(t, err)
+	key := "myKey"
+	group := "/custom/a/b"
+	value := "MyValue"
+	err = nacos.PublishConfig(key, group, value)
+	assert.Nil(t, err)
+}
+
 func Test_AddListener(t *testing.T) {
 	nacos, err := initNacosData(t)
 	assert.NoError(t, err)
diff --git a/config_center/nacos/listener.go b/config_center/nacos/listener.go
index 25c586586c7202e42ff44d6104e8132961add25a..0f16727b60d20d4ec482f2b23c4eb4f53612cf6d 100644
--- a/config_center/nacos/listener.go
+++ b/config_center/nacos/listener.go
@@ -35,11 +35,11 @@ func callback(listener config_center.ConfigurationListener, namespace, group, da
 	listener.Process(&config_center.ConfigChangeEvent{Key: dataId, Value: data, ConfigType: remoting.EventTypeUpdate})
 }
 
-func (l *nacosDynamicConfiguration) addListener(key string, listener config_center.ConfigurationListener) {
-	_, loaded := l.keyListeners.Load(key)
+func (nacos *nacosDynamicConfiguration) addListener(key string, listener config_center.ConfigurationListener) {
+	_, loaded := nacos.keyListeners.Load(key)
 	if !loaded {
 		_, cancel := context.WithCancel(context.Background())
-		err := (*l.client.Client()).ListenConfig(vo.ConfigParam{
+		err := (*nacos.client.Client()).ListenConfig(vo.ConfigParam{
 			DataId: key,
 			Group:  "dubbo",
 			OnChange: func(namespace, group, dataId, data string) {
@@ -49,14 +49,14 @@ func (l *nacosDynamicConfiguration) addListener(key string, listener config_cent
 		logger.Errorf("nacos : listen config fail, error:%v ", err)
 		newListener := make(map[config_center.ConfigurationListener]context.CancelFunc)
 		newListener[listener] = cancel
-		l.keyListeners.Store(key, newListener)
+		nacos.keyListeners.Store(key, newListener)
 	} else {
 		// TODO check goroutine alive, but this version of go_nacos_sdk is not support.
 		logger.Infof("profile:%s. this profile is already listening", key)
 	}
 }
 
-func (l *nacosDynamicConfiguration) removeListener(key string, listener config_center.ConfigurationListener) {
+func (nacos *nacosDynamicConfiguration) removeListener(key string, listener config_center.ConfigurationListener) {
 	// TODO: not supported in current go_nacos_sdk version
 	logger.Warn("not supported in current go_nacos_sdk version")
 }
diff --git a/config_center/zookeeper/impl.go b/config_center/zookeeper/impl.go
index 404243d4751146d1edc9a61d51cbb81d73c2ffb1..f8263e47c7f31035231e4b6f2ab805096addf2ff 100644
--- a/config_center/zookeeper/impl.go
+++ b/config_center/zookeeper/impl.go
@@ -41,6 +41,7 @@ const (
 	// ZkClient
 	//zookeeper client name
 	ZkClient = "zk config_center"
+	pathSeparator = "/"
 )
 
 type zookeeperDynamicConfiguration struct {
@@ -143,11 +144,21 @@ func (c *zookeeperDynamicConfiguration) GetProperties(key string, opts ...config
 	return string(content), nil
 }
 
-//For zookeeper, getConfig and getConfigs have the same meaning.
+// GetInternalProperty For zookeeper, getConfig and getConfigs have the same meaning.
 func (c *zookeeperDynamicConfiguration) GetInternalProperty(key string, opts ...config_center.Option) (string, error) {
 	return c.GetProperties(key, opts...)
 }
 
+// PublishConfig will put the value into Zk with specific path
+func (c *zookeeperDynamicConfiguration) PublishConfig(key string, group string, value string) error {
+	path := c.getPath(key, group)
+	err := c.client.CreateWithValue(path, []byte(value))
+	if err != nil {
+		return perrors.WithStack(err)
+	}
+	return nil
+}
+
 func (c *zookeeperDynamicConfiguration) GetRule(key string, opts ...config_center.Option) (string, error) {
 	return c.GetProperties(key, opts...)
 }
@@ -214,3 +225,17 @@ func (c *zookeeperDynamicConfiguration) closeConfigs() {
 func (c *zookeeperDynamicConfiguration) RestartCallBack() bool {
 	return true
 }
+
+func (c *zookeeperDynamicConfiguration) getPath(key string, group string) string {
+	if len(key) <= 0 {
+		return c.buildPath(group) 
+	}
+	return c.buildPath(group) + pathSeparator + key
+}
+
+func (c *zookeeperDynamicConfiguration) buildPath(group string) string {
+	if len(group) <= 0 {
+		group = config_center.DEFAULT_GROUP
+	}
+	return c.rootPath + pathSeparator + group
+}
diff --git a/config_center/zookeeper/impl_test.go b/config_center/zookeeper/impl_test.go
index 22e15193cba1b533a2b1b965a44bf9665a6a4e5e..e6349d4c3de4614aef4ebdefcb76f773d9418eb2 100644
--- a/config_center/zookeeper/impl_test.go
+++ b/config_center/zookeeper/impl_test.go
@@ -156,6 +156,18 @@ func Test_RemoveListener(t *testing.T) {
 	assert.Equal(t, "", listener.event)
 }
 
+func TestZookeeperDynamicConfiguration_PublishConfig(t *testing.T) {
+	value := "Test Data"
+	customGroup := "Custom Group"
+	ts, zk := initZkData(config_center.DEFAULT_GROUP, t)
+	defer ts.Stop()
+	err := zk.PublishConfig("myKey", customGroup, value)
+	assert.Nil(t, err)
+	result, err := zk.GetInternalProperty("myKey", config_center.WithGroup(customGroup))
+	assert.Nil(t, err)
+	assert.Equal(t, value, result)
+}
+
 type mockDataListener struct {
 	wg    sync.WaitGroup
 	event string
diff --git a/remoting/zookeeper/client.go b/remoting/zookeeper/client.go
index 21486aab59c3f9b44c25b68d7433f864a990149a..936b3b5acf39b103fbfcecd4bace4b6dbca8e944 100644
--- a/remoting/zookeeper/client.go
+++ b/remoting/zookeeper/client.go
@@ -392,8 +392,16 @@ func (z *ZookeeperClient) Close() {
 	logger.Warnf("zkClient{name:%s, zk addr:%s} exit now.", z.name, z.ZkAddrs)
 }
 
-// Create ...
+// Create will create the node recursively, which means that if the parent node is absent,
+// it will create parent node first.
+// And the value for the basePath is ""
 func (z *ZookeeperClient) Create(basePath string) error {
+	return z.CreateWithValue(basePath, []byte(""))
+}
+
+// Create will create the node recursively, which means that if the parent node is absent,
+// it will create parent node first.
+func (z *ZookeeperClient) CreateWithValue(basePath string, value []byte) error {
 	var (
 		err     error
 		tmpPath string
@@ -407,7 +415,7 @@ func (z *ZookeeperClient) Create(basePath string) error {
 		conn := z.Conn
 		z.Unlock()
 		if conn != nil {
-			_, err = conn.Create(tmpPath, []byte(""), 0, zk.WorldACL(zk.PermAll))
+			_, err = conn.Create(tmpPath, value, 0, zk.WorldACL(zk.PermAll))
 		}
 
 		if err != nil {
@@ -423,6 +431,8 @@ func (z *ZookeeperClient) Create(basePath string) error {
 	return nil
 }
 
+
+
 // Delete ...
 func (z *ZookeeperClient) Delete(basePath string) error {
 	var (