You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by il...@apache.org on 2021/01/11 11:17:15 UTC

[dubbo-website] branch master updated: dubbo-go blog, batch 2

This is an automated email from the ASF dual-hosted git repository.

iluo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-website.git


The following commit(s) were added to refs/heads/master by this push:
     new 839ecd3  dubbo-go blog, batch 2
839ecd3 is described below

commit 839ecd30d535fbc2cc393a1b9d2576c003c41986
Author: Ian Luo <ia...@gmail.com>
AuthorDate: Mon Jan 11 19:16:51 2021 +0800

    dubbo-go blog, batch 2
---
 content/zh/blog/news/dubbo-go-101.md               | 190 +++++++++++++
 content/zh/blog/news/dubbo-go-config-center.md     | 313 +++++++++++++++++++++
 content/zh/blog/news/dubbo-go-sentinel.md          | 161 +++++++++++
 .../dubbo-go/config-center/config-center-class.jpg | Bin 0 -> 60991 bytes
 static/imgs/blog/dubbo-go/config-center/design.png | Bin 0 -> 45181 bytes
 .../blog/dubbo-go/config-center/key-struct.png     | Bin 0 -> 34451 bytes
 .../dubbo-go/config-center/zookeeper-usercase.png  | Bin 0 -> 81623 bytes
 .../sentinel/dubbo-go-sentinel-provider-filter.png | Bin 0 -> 298046 bytes
 .../blog/dubbo-go/sentinel/sentinel-golang.png     | Bin 0 -> 29177 bytes
 9 files changed, 664 insertions(+)

diff --git a/content/zh/blog/news/dubbo-go-101.md b/content/zh/blog/news/dubbo-go-101.md
new file mode 100644
index 0000000..b2a2caf
--- /dev/null
+++ b/content/zh/blog/news/dubbo-go-101.md
@@ -0,0 +1,190 @@
+---
+title: "Dubbo Go 快速开始"
+linkTitle: "Dubbo Go 快速开始"
+date: 2021-01-11
+description: 本文介绍了如何通过一个 `hellowworld` 例子带领大家快速上手 Dubbo Go 框架
+---
+
+## 环境
+
+- Go编程环境
+- 启动zookeeper服务,也可以使用远程实例
+
+## 从服务端开始
+
+### 第一步:编写 `Provider` 结构体和提供服务的方法
+
+> https://github.com/dubbogo/dubbo-samples/blob/master/golang/helloworld/dubbo/go-server/app/user.go
+
+1. 编写需要被编码的结构体,由于使用 `Hessian2` 作为编码协议,`User` 需要实现 `JavaClassName` 方法,它的返回值在dubbo中对应User类的类名。
+
+```go
+type User struct {
+	Id   string
+	Name string
+	Age  int32
+	Time time.Time
+}
+
+func (u User) JavaClassName() string {
+	return "com.ikurento.user.User"
+}
+```
+
+1. 编写业务逻辑,`UserProvider` 相当于dubbo中的一个服务实现。需要实现 `Reference` 方法,返回值是这个服务的唯一标识,对应dubbo的 `beans` 和 `path` 字段。
+
+```go
+type UserProvider struct {
+}
+
+func (u *UserProvider) GetUser(ctx context.Context, req []interface{}) (*User, error) {
+	println("req:%#v", req)
+	rsp := User{"A001", "hellowworld", 18, time.Now()}
+	println("rsp:%#v", rsp)
+	return &rsp, nil
+}
+
+func (u *UserProvider) Reference() string {
+	return "UserProvider"
+}
+```
+
+1. 注册服务和对象
+
+```go
+func init() {
+	config.SetProviderService(new(UserProvider))
+	// ------for hessian2------
+	hessian.RegisterPOJO(&User{})
+}
+```
+
+### 第二步:编写主程序
+
+> https://github.com/dubbogo/dubbo-samples/blob/master/golang/helloworld/dubbo/go-server/app/server.go
+
+1. 引入必需的dubbo-go包
+
+```go
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+	"github.com/apache/dubbo-go/config"
+	_ "github.com/apache/dubbo-go/registry/protocol"
+	_ "github.com/apache/dubbo-go/common/proxy/proxy_factory"
+	_ "github.com/apache/dubbo-go/filter/impl"
+	_ "github.com/apache/dubbo-go/cluster/cluster_impl"
+	_ "github.com/apache/dubbo-go/cluster/loadbalance"
+	_ "github.com/apache/dubbo-go/registry/zookeeper"
+
+	_ "github.com/apache/dubbo-go/protocol/dubbo"
+)
+```
+
+1. main 函数
+
+```go
+func main() {
+	config.Load()
+}
+```
+
+### 第三步:编写配置文件并配置环境变量
+
+1. 参考 [log](https://github.com/dubbogo/dubbo-samples/blob/master/golang/helloworld/dubbo/go-server/profiles/release/log.yml) 和 [server](https://github.com/dubbogo/dubbo-samples/blob/master/golang/helloworld/dubbo/go-server/profiles/release/server.yml) 编辑配置文件。
+
+主要编辑以下部分:
+
+- `registries` 结点下需要配置zk的数量和地址
+- `services` 结点下配置服务的具体信息,需要配置 `interface` 配置,修改为对应服务的接口名,服务的key对应第一步中 `Provider` 的 `Reference` 返回值
+
+1. 把上面的两个配置文件分别配置为环境变量
+
+```shell
+export CONF_PROVIDER_FILE_PATH="xxx"
+export APP_LOG_CONF_FILE="xxx"
+```
+
+## 接着是客户端
+
+### 第一步:编写客户端 `Provider`
+
+> https://github.com/dubbogo/dubbo-samples/blob/master/golang/helloworld/dubbo/go-client/app/user.go
+
+1. 参考服务端第一步的第一点。
+2. 与服务端不同的是,提供服务的方法作为结构体的参数,不需要编写具体业务逻辑。另外,`Provider` 不对应dubbo中的接口,而是对应一个实现。
+
+```go
+type UserProvider struct {
+	GetUser func(ctx context.Context, req []interface{}, rsp *User) error
+}
+
+func (u *UserProvider) Reference() string {
+	return "UserProvider"
+}
+```
+
+1. 注册服务和对象
+
+```go
+func init() {
+	config.SetConsumerService(userProvider)
+	hessian.RegisterPOJO(&User{})
+}
+```
+
+### 第二步:编写客户端主程序
+
+> https://github.com/dubbogo/dubbo-samples/blob/master/golang/helloworld/dubbo/go-client/app/client.go
+
+1. 引入必需的dubbo-go包
+
+```go
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+	"github.com/apache/dubbo-go/config"
+	_ "github.com/apache/dubbo-go/registry/protocol"
+	_ "github.com/apache/dubbo-go/common/proxy/proxy_factory"
+	_ "github.com/apache/dubbo-go/filter/impl"
+	_ "github.com/apache/dubbo-go/cluster/cluster_impl"
+	_ "github.com/apache/dubbo-go/cluster/loadbalance"
+	_ "github.com/apache/dubbo-go/registry/zookeeper"
+
+	_ "github.com/apache/dubbo-go/protocol/dubbo"
+)
+```
+
+1. main 函数
+
+```go
+func main() {
+	config.Load()
+	time.Sleep(3e9)
+
+	println("\n\n\nstart to test dubbo")
+	user := &User{}
+	err := userProvider.GetUser(context.TODO(), []interface{}{"A001"}, user)
+	if err != nil {
+		panic(err)
+	}
+	println("response result: %v\n", user)
+}
+func println(format string, args ...interface{}) {
+	fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...)
+}
+```
+
+### 第三步:编写配置文件并配置环境变量
+
+1. 参考 [log](https://github.com/dubbogo/dubbo-samples/blob/master/golang/helloworld/dubbo/go-client/profiles/release/log.yml) 和 [client](https://github.com/dubbogo/dubbo-samples/blob/master/golang/helloworld/dubbo/go-client/profiles/release/client.yml) 编辑配置文件。
+
+主要编辑以下部分:
+
+- `registries` 结点下需要配置zk的数量和地址
+- `references` 结点下配置服务的具体信息,需要配置 `interface` 配置,修改为对应服务的接口名,服务的key对应第一步中 `Provider` 的 `Reference` 返回值
+
+1. 把上面的两个配置文件费别配置为环境变量,为防止log的环境变量和服务端的log环境变量冲突,建议所有的环境变量不要做全局配置,在当前起效即可。
+
+```shell
+export CONF_CONSUMER_FILE_PATH="xxx"
+export APP_LOG_CONF_FILE="xxx"
+```
\ No newline at end of file
diff --git a/content/zh/blog/news/dubbo-go-config-center.md b/content/zh/blog/news/dubbo-go-config-center.md
new file mode 100644
index 0000000..a5532f1
--- /dev/null
+++ b/content/zh/blog/news/dubbo-go-config-center.md
@@ -0,0 +1,313 @@
+---
+title: "dubbo-go 中如何实现远程配置管理?"
+linkTitle: "dubbo-go 中如何实现远程配置管理?"
+date: 2021-01-11
+description: 本文介绍了如何在 dubbo-go 中使用配置中心进行远程配置管理
+---
+
+之前在 Apache/dubbo-go(以下简称 dubbo-go )社区中,有同学希望配置文件不仅可以放于本地,还可以放于配置管理中心里。那么,放在本地和配置管理中心究竟有哪些不一样呢?
+
+放在本地,每次更新需要重启,配置文件管理困难,无法做到实时更新即刻生效。此外,本地文件还依赖人工版本控制,在微服务的场景下,大大的增加了运维的成本与难度。
+
+而配置管理中心提供了统一的配置文件管理,支持文件更新、实时同步、统一版本控制、权限管理等功能。
+
+## 目标
+
+基于以上几个背景,可以总结出以下**目标**
+
+- 与 Dubbo 现有的配置中心内的配置文件兼容,降低新增语言栈的学习成本;
+- 支持多种配置文件格式;
+- 支持主流配置中心,适应不一样的使用场景,实现高扩展的配置下发;
+
+## 配置中心
+
+配置中心在 dubbo-go 中主要承担以下场景的职责:
+
+1. 作为外部化配置中心,即存储 dubbo.properties 配置文件,此时,key 值通常为文件名如 dubbo.properties , value 则为配置文件内容。
+2. 存储单个配置项,如各种开关项、常量值等。
+3. 存储服务治理规则,此时 key 通常按照 “服务名 + 规则类型” 的格式来组织,而 value 则为具体的治理规则。
+
+就目前而言,dubbo-go 首要支持的是 Dubbo 中支持的开源配置中心,包括:
+1. Apollo:携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
+2. ZooKeeper:一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 Hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
+3. Nacos: Alibaba 开源的配置管理组件,提供了一组简单易用的特性集,帮助您实现动态服务发现、服务配置管理、服务及流量管理。
+
+而考虑到某些公司内部有自身的研发的配置中心,又或者当前流行而 Dubbo 尚未支持的配置中心,如 etcd,我们的核心在于设计一套机制,允许我们,也包括用户,可以通过扩展接口新的实现,来快速接入不同的配置中心。
+
+那在 dubbo-go 中究竟怎么实现呢?我们的答案是:**基于动态的插件机制在启动时按需加载配置中心的不同实现。**
+
+实现该部分功能放置于一个独立的子项目中,见: https://github.com/apache/dubbo-go/tree/master/config_center
+
+### dubbo-go 设计
+
+原逻辑为:启动时读取本地配置文件,将其加载进内存,通过配置文件中的配置读取注册中心的信息获取服务提供者,注册服务消费者。
+
+有些读者会有点困惑,不是说好了使用配置中心的,为什么现在又要读取本地配置呢?答案就是,读取的这部分信息分成两部分:
+
+- 使用什么作为配置中心;
+- 该配置中心的元数据,比如说使用 zookeeper 作为配置中心,那么 zookeeper 的链接信息就是元数据,毕竟我们只有在知道了链接信息之后才能连上 zookeeper;
+
+在改造的时候,需要考虑以下的问题:
+
+**1、如何实现支持多个配置中心?如何实现按需加载?**
+
+通过抽象 DynamicConfiguration 让开发者可以快速支持多个配置中心。使用者导入指定的组件包后,在启动阶段将需要的组件加载进内存中,以便给程序按需调用,如下图绿色部分。
+
+**2、配置中心的配置加载阶段在什么时候?**
+
+应在读取配置文件阶段后,读取并解析本地配置文件中配置中心信息。初始化配置中心链接,读取 /dubbo/config/dubbo/dubbo.properties 与 /dubbo/config/dubbo/应用名/dubbo.properties ,并将其加载到内存之中覆盖原有配置,监听其变更,实时更新至内存,如下图蓝色部分:
+![](/imgs/blog/dubbo-go/config-center/config-center-class.jpg)
+
+#### ConfigCenterFactory
+
+使用者加载对应配置中心模块后,在初始化阶段加入各配置中心模块往其中注册其初始化类。
+
+```golang
+package extension
+
+import (
+	"github.com/apache/dubbo-go/config_center"
+)
+
+var (
+	configCenterFactories = make(map[string]func() config_center.DynamicConfigurationFactory)
+)
+
+// SetConfigCenterFactory sets the DynamicConfigurationFactory with @name
+func SetConfigCenterFactory(name string, v func() config_center.DynamicConfigurationFactory) {
+	configCenterFactories[name] = v
+}
+
+// GetConfigCenterFactory finds the DynamicConfigurationFactory with @name
+func GetConfigCenterFactory(name string) config_center.DynamicConfigurationFactory {
+	if configCenterFactories[name] == nil {
+		panic("config center for " + name + " is not existing, make sure you have import the package.")
+	}
+	return configCenterFactories[name]()
+}
+```
+
+#### DynamicConfigurationFactory
+
+整个动态配置中心的关键点就在 DynamicConfigurationFactory 上,其中通过解析内部自定义的 URL ,获取其协议类型,反射其参数,用于创建配置中心的链接。
+
+```golang
+package config_center
+
+import (
+	"github.com/apache/dubbo-go/common"
+)
+
+// DynamicConfigurationFactory gets the DynamicConfiguration
+type DynamicConfigurationFactory interface {
+	GetDynamicConfiguration(*common.URL) (DynamicConfiguration, error)
+}
+```
+
+如:
+
+配置文件中配置:
+
+```yaml
+config_center:
+  protocol: zookeeper
+  address: 127.0.0.1:2181
+  namespace: test
+```
+
+dubbo-go 内部会解析为:
+
+```
+zookeeper://127.0.0.1:2181?namespace=test
+```
+
+在内部传递,用于初始化配置中心链接。
+
+**PS:** 在 dubbo-go 中到处可见这种内部协议,透彻理解这个内部协议对阅读 dubbo-go 代码很有帮助。
+
+#### DynamicConfiguration
+
+该接口规定了各个配置中心需要实现的功能:
+
+- 配置数据反序列化方式:目前只有 Properties 转换器,参见:DefaultConfigurationParser 。
+- 增加监听器:用于增加监听数据变化后增加特定逻辑(受限于配置中心 client 端实现)。
+- 删除监听器:删除已有监听器(受限于配置中心 client 端实现,目前所知 nacos client 没有提供该方法)。
+- 获取路由配置:获取路由表配置。
+- 获取应用级配置:获取应用层级配置,如:协议类型配置等。
+
+```golang
+// DynamicConfiguration for modify listener and get properties file
+type DynamicConfiguration interface {
+	Parser() parser.ConfigurationParser
+	SetParser(parser.ConfigurationParser)
+	AddListener(string, ConfigurationListener, ...Option)
+	RemoveListener(string, ConfigurationListener, ...Option)
+	// GetProperties get properties file
+	GetProperties(string, ...Option) (string, error)
+
+	// GetRule get Router rule properties file
+	GetRule(string, ...Option) (string, error)
+
+	// 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
+
+	// RemoveConfig will remove the config white the (key, group) pair
+	RemoveConfig(string, string) error
+
+	// GetConfigKeysByGroup will return all keys with the group
+	GetConfigKeysByGroup(group string) (*gxset.HashSet, error)
+}
+```
+
+### 实现
+
+![](/imgs/blog/dubbo-go/config-center/design.png)
+
+优先考虑与现有 Dubbo 设计兼容,从而降低使用者的学习成本,dubbo-admin 作为服务提供者实现应用级配置管理, dubbo-go 作为消费端实现配置下发管理功能。下面以 ZooKeeper 为例,对服务提供者与服务消费者进行整体流程分析。
+
+#### 如何存储配置管理
+
+dubbo-admin 配置管理中增加 global 配置,ZooKeeper 中会自动生成其对应配置节点,内容均为 dubbo-admin 中设置的配置。
+
+1. /dubbo/config/dubbo/dubbo.properties 对应全局配置文件。
+2. /dubbo/config/dubbo/ 应用名 /dubbo.properties 对应指定应用配置文件。
+
+##### 节点路径
+
+![](/imgs/blog/dubbo-go/config-center/key-struct.png)
+
+上图展示了 dubbo.properties 文件在 ZooKeeper 和 Apollo 中的存储结构:
+
+**ZooKeeper**
+
+- 命名空间 namespace 都为:Dubbo
+- 分组 group :全局级别为 dubbo , 所有应用共享;应用级别为应用名 demo-provider ,只对该应用生效
+- key : dubbo.properties
+
+**Apollo**
+
+- app_id : 自由指定,默认:dubbo ,最好与 zookeeper  namespace 一致
+- cluster : 自由指定,最好与 zookeeper group 一致
+- 命名空间 namespace : dubbo.properties
+
+ZooKeeper 与 Apollo 最大的不一样就在于 dubbo.properties 所在的节点。
+
+#### 实现配置管理中心支持
+
+以 Apollo 为例,简单的介绍,如何实现支持一个新的配置管理中心。
+
+##### 选择配置管理中心 Client / SDK
+
+本例中使用的 Apollo Go Client 为:https://github.com/zouyx/agollo 。
+
+**PS:** 如没找到,自己实现也是可以的哦。
+
+##### 节点路径
+
+因为每个配置管理中心的存储结构各有特点,导致 Dubbo 在使用外部配置管理中心时,存储配置节点的结构不一样。在 dubbo-configcenter 找到希望支持的配置管理中心,而本例中 Apollo 则在 ApolloDynamicConfiguration.java 。
+
+注释中表明,Apollo namespace = governance (governance .properties) 用于治理规则,namespace = dubbo (dubbo.properties) 用于配置文件。
+
+##### 实现 DynamicConfiguration
+
+新建创建客户端方法,最好客户端保持为单例。
+
+```golang
+func newApolloConfiguration(url *common.URL) (*apolloConfiguration, error) {
+	c := &apolloConfiguration{
+		url: url,
+	}
+	configAddr := c.getAddressWithProtocolPrefix(url)
+	configCluster := url.GetParam(constant.CONFIG_CLUSTER_KEY, "")
+
+	appId := url.GetParam(constant.CONFIG_APP_ID_KEY, "")
+	namespaces := getProperties(url.GetParam(constant.CONFIG_NAMESPACE_KEY, cc.DEFAULT_GROUP))
+	c.appConf = &config.AppConfig{
+		AppID:         appId,
+		Cluster:       configCluster,
+		NamespaceName: namespaces,
+		IP:            configAddr,
+	}
+
+	agollo.InitCustomConfig(func() (*config.AppConfig, error) {
+		return c.appConf, nil
+	})
+
+	return c, agollo.Start()
+}
+```
+
+以下为必须实现的方法,以下方法用于获取配置中心配置。
+
+- GetInternalProperty:在配置文件(Apollo 为 namespace)中,根据 key 获取对应 value;
+- GetRule:获取治理配置文件(Apollo 为 namespace);
+- GetProperties:获取整个配置文件(Apollo 为 namespace);
+
+可选择实现的方法,如不实现,则不能动态更新 dubbo-go 中配置信息。
+
+- RemoveListener
+- AddListener
+
+而 Parser & SetParser 使用默认实现即可,默认为 Properties 转换器。
+
+更多信息,参考:dubbo-go-apollo ,详情参考: https://github.com/apache/dubbo-go/tree/master/config_center/apollo
+
+### 使用方法
+
+从上面的设计里面,也能大概猜到怎么使用了:
+
+![](/imgs/blog/dubbo-go/config-center/zookeeper-usercase.png)
+
+很显然,使用配置中心并不复杂,只需要把对应的依赖引入进来。在包初始化的时候,会创建出来对应的配置中心的实现。比如说加载 ZooKeeper 或者 Apollo 作为配置中心:
+
+**ZooKeeper**
+
+```golang
+_ "github.com/apache/dubbo-go/config_center/zookeeper"
+```
+
+**Apollo**
+
+```golang
+_ "github.com/apache/dubbo-go/config_center/apollo"
+```
+
+当然仅仅加载还不够,比如说虽然我加载了 zookeeper,但是我还需要知道怎么连上这个配置中心,即前面提到的配置中心的元数据,这部分信息是需要在本地配置出来的。比如说:
+
+**ZooKeeper**
+
+```yaml
+config_center:
+  protocol: "zookeeper"
+  address: "127.0.0.1:2181"
+```
+
+**Apollo**
+
+如果需要使用 Apollo 作为配置中心,请提前创建 namespace: dubbo.properties,用于配置管理。
+
+```yaml
+config_center:
+  protocol: "apollo"
+  address: "127.0.0.1:8070"
+  app_id: test_app
+  cluster: dev
+```
+
+## 总结
+
+更加具体的实现,我就不详细论述,大家可以去看源码,欢迎大家持续关注,或者贡献代码。
+
+整个配置中心的功能,麻雀虽小,但五脏俱全。目前并不算是十分完善,但是整个框架层面上来说,是走在了正确的路上。从扩展性来说,是比较便利。目前支持的配置中心还不够丰富,只有 ZooKeeper 与 Apollo ,支持的配置文件格式也只有 properties ,虽然能满足基本使用场景,距离完善还有还长远的路。
+
+**未来计划:**
+
+- Nacos(等待发布 )
+- etcd(正在开发)
+- consul(未支持)
+- 丰富的文件配置格式,如:yml , xml 等
+
+**本文作者:** 邹毅贤,Github ID @zouyx,开源爱好者,就职于 SheIn 供应链部门,负责供应链开放平台
\ No newline at end of file
diff --git a/content/zh/blog/news/dubbo-go-sentinel.md b/content/zh/blog/news/dubbo-go-sentinel.md
new file mode 100644
index 0000000..ed36c4b
--- /dev/null
+++ b/content/zh/blog/news/dubbo-go-sentinel.md
@@ -0,0 +1,161 @@
+---
+title: "在dubbo-go中使用sentinel"
+linkTitle: "在dubbo-go中使用sentinel"
+date: 2021-01-11
+description: 本文介绍了如何在 dubbo-go 中使用限流组件 sentinel
+---
+
+
+时至今日,Apache/dubbo-go(以下简称 dubbo-go )项目在功能上已经逐步对齐java版本,稳定性也在不同的生产环境得到了验证。社区便开始再服务治理、监控等方向发力。随着 1.2和1.3 版本发布, dubbo-go 新增了大量此类新feature。
+
+今天我们聊一聊限流相关话题,此前dubbo-go已经支持了[tps limit](https://github.com/apache/dubbo-go/pull/237)、[execute limit ](https://github.com/apache/dubbo-go/pull/246)、[hystrix](https://github.com/apache/dubbo-go/pull/133) 的内置filter,用户只要简单配置就能马上用上。但我们知道,在 java 的 dubbo 生态中,有一项限流工具被广泛使用,那就是sentinel。sentinel因为强大的动态规划配置、优秀的dashboard以及对dubbo的良好适配,成为众多使用dubbo的企业选用限流工具的不二之选。
+
+就在前些日子,社区非常高兴得知 Sentinel Golang 首个版本 0.1.0 正式发布,这使得 dubbo-go也可以使用 sentinel 作为工具进行一些服务治理、监控的工作了。随着sentinel golang的健壮,我们相信用户马上可以像sentinel管理java dubbo服务那样管理dubbo-go的服务了。
+
+完成sentinel golang的dubbo-adapter其实非常简单,这得益于dubbo-go早就完成了filter链的构造,用户可以自定义filter,并且灵活的安排其执行顺序。在1.3发布后,增加了filter中的context传递,构建sentinel/adapter/dubbo更为方便。
+
+我们以其中的provider filter适配为例:
+
+![](/imgs/blog/dubbo-go/sentinel/dubbo-go-sentinel-provider-filter.png)
+
+此 filter 实现了 dubbo-go的filter接口,只要用户在服务启动时将此filter加载到dubbo-go中,即可使用此filter。 
+
+![](/imgs/blog/dubbo-go/sentinel/sentinel-golang.png)
+
+sentinel实现原理与其他限流、熔断库大同小异,底层是用的滑动窗口算法。与hystrix等框架相比不同点是设计理念,Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。
+
+下面我整理了完整的使用流程:(注意:dubbo-go版本请使用1.3.0-rc3及其以上版本)
+
+在dubbo-go中使用sentinel主要分为以下几步:
+
+1. 初始化sentinel
+2. 将sentinel注入dubbo-go的filter
+3. 初始化dubbo-go
+4. 配置规划
+
+## 初始化sentinel
+
+示例代码:
+
+```go
+import (
+	sentinel "github.com/alibaba/sentinel-golang/api"
+)
+
+func initSentinel() {
+	err := sentinel.InitWithLogDir(confPath, logDir)
+	if err != nil {
+		// 初始化 Sentinel 失败
+	}
+}
+```
+
+## 将sentinel注入dubbo-go的filter
+
+你可以通过import包的形式执行,执行其中的init()来注入filter
+
+```go
+import (
+	_ "github.com/alibaba/sentinel-golang/adapter/dubbo"
+)
+```
+
+也可以手动执行,给你的filter取上自己想要的名字
+
+```go
+import (
+  "github.com/apache/dubbo-go/common/extension"
+  sd "github.com/alibaba/sentinel-golang/adapter/dubbo"
+)
+
+func main(){
+  extension.SetFilter("myConsumerFilter",sd.GetConsumerFilter())
+  extension.SetFilter("myProviderFilter",sd.GetConsumerFilter())
+}
+```
+
+完成以上步骤,你就可以在需要的dubbo接口配置里写入sentinel的filterName,构建起接口的filter链条。比如以下以consumer.yml配置文件为例
+
+```yml
+references:
+  "UserProvider":
+    registry: "hangzhouzk"
+    protocol : "dubbo"
+    interface : "com.ikurento.user.UserProvider"
+    cluster: "failover"
+    filter: "myConsumerFilter"
+    methods :
+    - name: "GetUser"
+      retries: 3
+```
+
+## 初始化dubbo-go
+
+到这一步,你只需要正常启动dubbo-go程序就完成了服务启动。用以下代码做一个较为完整举例
+
+```go
+import (
+	hessian "github.com/apache/dubbo-go-hessian2"
+	sd "github.com/alibaba/sentinel-golang/adapter/dubbo"
+)
+
+import (
+	"github.com/apache/dubbo-go/common/logger"
+	_ "github.com/apache/dubbo-go/common/proxy/proxy_factory"
+	"github.com/apache/dubbo-go/config"
+	_ "github.com/apache/dubbo-go/filter/impl"
+	_ "github.com/apache/dubbo-go/protocol/dubbo"
+	_ "github.com/apache/dubbo-go/registry/protocol"
+
+	_ "github.com/apache/dubbo-go/cluster/cluster_impl"
+	_ "github.com/apache/dubbo-go/cluster/loadbalance"
+	_ "github.com/apache/dubbo-go/registry/zookeeper"
+	"github.com/apache/dubbo-go/common/extension"
+)
+
+func main() {
+
+	hessian.RegisterPOJO(&User{})
+  extension.SetFilter("myConsumerFilter",sd.GetConsumerFilter())
+  extension.SetFilter("myProviderFilter",sd.GetConsumerFilter())
+	config.Load()
+
+	// init finish, do your work
+	test()
+}
+```
+
+## 规划配置
+
+sentinel以强大的规划配置吸引了很多使用者,其提供动态数据源接口进行扩展,用户可以通过动态文件或 etcd 等配置中心来动态地配置规则。但目前sentinel-golang作为破蛋版本,动态配置还在开发中
+
+### 动态数据源
+
+(开发中)Sentinel 提供动态数据源接口进行扩展,用户可以通过动态文件或 etcd 等配置中心来动态地配置规则。
+
+### 硬编码方式
+
+Sentinel 也支持原始的硬编码方式加载规则,可以通过各个模块的 `LoadRules(rules)` 方法加载规则。以下是硬编码方式对某个method在consumer端的QPS流控:
+
+```go
+_, err := flow.LoadRules([]*flow.FlowRule{
+	{
+		ID:                666,
+		Resource:         "dubbo:consumer:com.ikurento.user.UserProvider:myGroup:1.0.0:hello()",
+		MetricType:        flow.QPS,
+		Count:             10,
+		ControlBehavior:   flow.Reject,
+	},
+})
+if err != nil {
+	// 加载规则失败,进行相关处理
+}
+```
+
+# 总结
+
+更加具体的实现,我就不详细论述,大家可以去看源码进一步了解。
+
+最后,欢迎大家持续关注,或者贡献代码,期待dubbo-go在2020年在云原生领域继续突破。
+
+dubbo-go仓库地址:https://github.com/apache/dubbo-go
\ No newline at end of file
diff --git a/static/imgs/blog/dubbo-go/config-center/config-center-class.jpg b/static/imgs/blog/dubbo-go/config-center/config-center-class.jpg
new file mode 100644
index 0000000..3fc7600
Binary files /dev/null and b/static/imgs/blog/dubbo-go/config-center/config-center-class.jpg differ
diff --git a/static/imgs/blog/dubbo-go/config-center/design.png b/static/imgs/blog/dubbo-go/config-center/design.png
new file mode 100644
index 0000000..4c035fd
Binary files /dev/null and b/static/imgs/blog/dubbo-go/config-center/design.png differ
diff --git a/static/imgs/blog/dubbo-go/config-center/key-struct.png b/static/imgs/blog/dubbo-go/config-center/key-struct.png
new file mode 100644
index 0000000..cebcd37
Binary files /dev/null and b/static/imgs/blog/dubbo-go/config-center/key-struct.png differ
diff --git a/static/imgs/blog/dubbo-go/config-center/zookeeper-usercase.png b/static/imgs/blog/dubbo-go/config-center/zookeeper-usercase.png
new file mode 100644
index 0000000..47b9ea6
Binary files /dev/null and b/static/imgs/blog/dubbo-go/config-center/zookeeper-usercase.png differ
diff --git a/static/imgs/blog/dubbo-go/sentinel/dubbo-go-sentinel-provider-filter.png b/static/imgs/blog/dubbo-go/sentinel/dubbo-go-sentinel-provider-filter.png
new file mode 100644
index 0000000..3806989
Binary files /dev/null and b/static/imgs/blog/dubbo-go/sentinel/dubbo-go-sentinel-provider-filter.png differ
diff --git a/static/imgs/blog/dubbo-go/sentinel/sentinel-golang.png b/static/imgs/blog/dubbo-go/sentinel/sentinel-golang.png
new file mode 100644
index 0000000..03df855
Binary files /dev/null and b/static/imgs/blog/dubbo-go/sentinel/sentinel-golang.png differ