tegola是一个用Golang编写的开源矢量瓦片服务,github地址
在运行启动命令时设置toml格式的配置文件如下:
./tegola serve --config=/path/to/config.toml
配置文件中可设置相关信息如下:
tile_buffer = 64
[webserver]
port = ":9090"
[cache]
type="file" # cache type
basepath="/tmp/tegola" # cache specific config
# register data providers
[[providers]]
name = "test_postgis" # provider name is referenced from map layers
type = "postgis" # the type of data provider. currently only supports postgis
uri = "postgres://tegola:supersecret@localhost:5432/tegola?sslmode=prefer" # PostGIS connection string (required)
srid = 3857 # The default srid for this provider. If not provided it will be WebMercator (3857)
# Example data
[[providers.layers]]
name = "landuse" # will be encoded as the layer name in the tile
tablename = "gis.zoning_base_3857" # sql or table_name are required
geometry_fieldname = "geom" # geom field. default is geom
id_fieldname = "gid" # geom id field. default is gid
srid = 4326 # the SRID of the geometry field if different than
[[providers.layers]]
name = "roads" # will be encoded as the layer name in the tile
tablename = "gis.zoning_base_3857" # sql or table_name are required
geometry_fieldname = "geom" # geom field. default is geom
id_fieldname = "gid" # geom id field. default is gid
fields = [ "class", "name" ] # Additional fields to include in the select statement.
[[providers.layers]]
name = "rivers" # will be encoded as the layer name in the tile
# Custom sql to be used for this layer.
# Note that the geometry field is wrapped in a ST_AsBinary()
sql = "SELECT gid, ST_AsBinary(geom) AS geom FROM gis.rivers WHERE geom && !BBOX!"
# maps are made up of layers
[[maps]]
name = "zoning" # used in the URL to reference this map (/maps/:map_name)
tile_buffer = 0 # number of pixels to extend a tile's clipping area
[[maps.layers]]
provider_layer = "test_postgis.landuse" # must match a data provider layer
min_zoom = 12 # minimum zoom level to include this layer
max_zoom = 16 # maximum zoom level to include this layer
[maps.layers.default_tags] # table of default tags to encode in the tile. SQL statements will override
class = "park"
[[maps.layers]]
provider_layer = "test_postgis.rivers" # must match a data provider layer
min_zoom = 10 # minimum zoom level to include this layer
max_zoom = 18 # maximum zoom level to include this layer
但是目前tegola是不支持热更新的,修改了配置文件必须重新运行如下命令,才能实现矢量瓦片服务的更新
./tegola serve --config=/path/to/config.toml
解决这个问题,首先想着是找找代码库的issue看看有没有什么思路
在搜索了watch config 关键字后,果然找到了一条
顺藤摸瓜找到提issue的大佬fork了一份自己的tegola代码库,并且实现了一个带有热更新功能的tegola版本(版本地址)
可以看看他主要的初次提交https://github.com/jchamberlain/tegola/commit/b9f1aa838e43b60e5333dc39c306e10a0a32472a#diff-6fee72d756bffc1ccc3388d99d3a5ac70642694c9d90640705903c5823ce217e
主要关注source.go与file.go两个文件,可以看到主要利用for select特性,监听toml文件的变化,loadApp实现热更新
于是同理,我们可以在参照大佬实现增加一个nacos.go的文件,把主要的toml配置放置在nacos中,基于nacos的监听机制,nacos中toml配置文件更新了,就进行tegola的热更新
nacos.go完整代码如下:
package source
import (
"context"
"fmt"
"github.com/go-spatial/tegola/internal/env"
"github.com/go-spatial/tegola/internal/log"
"github.com/go-spatial/tegola/nacos"
)
// NacosConfigSource is a config source for loading and watching setting in nacos.
type NacosConfigSource struct {
ip string
port string
nameSpaceId string
dataId string
group string
}
func (s *NacosConfigSource) init(options env.Dict) error {
var err error
ip, err := options.String("ip", nil)
if err != nil {
return err
}
port, err := options.String("port", nil)
if err != nil {
return err
}
nameSpaceId, err := options.String("nameSpaceId", nil)
if err != nil {
return err
}
dataId, err := options.String("dataId", nil)
if err != nil {
return err
}
group, err := options.String("group", nil)
if err != nil {
return err
}
s.ip = ip
s.port = port
s.nameSpaceId = nameSpaceId
s.dataId = dataId
s.group = group
return nil
}
func (s *NacosConfigSource) Type() string {
return "nacos"
}
// LoadAndWatch will read all the files in the configured directory and then keep watching the directory for changes.
func (s *NacosConfigSource) LoadAndWatch(ctx context.Context) (ConfigWatcher, error) {
appWatcher := ConfigWatcher{
Updates: make(chan App),
Deletions: make(chan string),
}
// First check that nacos config exists and is readable.
nacos.Init(s.ip, s.port, s.nameSpaceId)
content, err := nacos.Client.Get(s.dataId, s.group)
if err != nil {
return appWatcher, fmt.Errorf("nacos config not readable: %s", err)
}
go func() {
s.loadApp(content, appWatcher.Updates)
err = nacos.Client.Listen(s.dataId, s.group, func(content string) {
fmt.Println(content)
s.loadApp(content, appWatcher.Updates)
})
if err != nil {
fmt.Println(err.Error())
}
for {
select {
case <-ctx.Done():
log.Info("Exiting watcher...")
appWatcher.Close()
return
}
}
}()
return appWatcher, nil
}
// loadApp reads nacos config content and loads the app into the updates channel.
func (s *NacosConfigSource) loadApp(content string, updates chan App) {
if app, err := parseAppFromNacos(content, s.nameSpaceId+s.group+s.dataId); err == nil {
// fmt.Println(app)
updates <- app
} else {
log.Errorf("Failed to parse nacos %s-%s-%s:%s", s.nameSpaceId, s.group, s.dataId, err)
}
}
同时在大佬的source.go中增加type类型为nacos的逻辑
tegola启动时的配置文件test_nacos.toml这样配置:
tile_buffer = 64
[webserver]
port = ":9090"
[app_config_source]
ip = '127.0.0.1'
port = ':8848'
type = "nacos"
nameSpaceId = 'tegola'
dataId = 'tegola'
group = 'DEFAULT_GROUP'
如上在app_config_source(大佬实现的热更新配置区域)里面设置nacos相关信息,主要关注type=“nacos”
然后启动tegola时运行如下就完成了监听nacos实现热更新的需求了!
./tegola serve --config=/path/to/test_nacos.toml