0%

为什么要用配置中心

Spring boot项目在启动时会加载application.properties(或yaml)里的配置,如果修改了application.properties,需要重新打包、部署,当服务有多个实例,需要每个都重新部署。配置中心就是用来解决这个问题的,我们所配置内容放在配置中心统一管理,项目启动时先去配置中心拉取配置,再用这些配置执行启动操作。如果配置有变更,在配置中心修改后,只需要一一重启服务,即可完成配置更新。有些配置中心甚至不需要重启,支持配置推送,比如我们今天介绍的Spring cloud zookeeper config。

Spring Cloud Zookeeper Config 介绍

Zookeeper提供了一个类似目录树的存储结构,允许客户端存储任意数据,如:配置数据。

Spring Cloud Zookeeper Config是Spring Cloud Config Server和Client的替代方案(这个方案需要起一个server服务,依赖git存储配置),在bootstrap阶段,加载配置到Spring环境中。

默认情况下,配置存储在/config节点下。Spring Cloud Zookeeper Config会基于应用程序名称和profile创建多个PropertySource模拟Spring Cloud Config顺序从Zookeeper读取并解析配置。

例如,应用名是testApp,profile是dev会创建下面几个property源:

1
2
3
4
/config/testApp,dev
/config/testApp
/config/application,dev
/config/application

配置优先级是从上至下的。/config/application 会应用到所有使用zookeeper作配置中心的项目上,/config/testApp 只对应用名为testApp的项目有效.

阅读全文 »

安全起见,我们希望用户使用https协议访问网站,但是在不输协议的时候,浏览器默认使用的是http协议。如果之前使用的是http协议,搜索引擎也会索引http协议的链接,用户点击打开的也是http协议。 出于对搜索引擎友好起见,这种场景我们一般使用301重定向,告诉搜索引擎已经永久转移到一个新地址,以后索引新地址。 之前我的博客一直存在这个问题,前端用kong,处理wordpress加了个nginx,kong和nginx之间http协议通讯。之前没有kong的时候,在nginx上配置重定向所有http到https,但是加了kong,不能这么做了,因为不管用户访问kong用的是http还是https,到nginx都是http。 今天抽了点时间写了个kong插件,完美解决这个问题,欢迎fork kong-plugin-http301https

Kong默认的管理接口,未加任何安全校验,如果暴露在公网,随时可能被坏人发现,随意修改我们的配置。 Kong admin ui本身是个纯前端项目,没有额外的安全措施来保护您的Kong,未来也不可能加上后端代码实现账户授权。 Custom Headers功能,就是为了解决安全问题而开发的。

阅读全文 »

这段时间在学习kong,用postman或是curl操作kong admin api始终不太方便.有个开源项目叫kong dashboard,但貌似不支持最新版的kong。 于是自己用Vue和iView写了一个简单的管理界面,目前只支持Service,Route,Upstream,Target的增删改查,后续会添加更多功能。项目已托管到github: https://github.com/pocketdigi/kong-admin-ui 纯前端项目,所有对Kong admin api的操作都是浏览器发出的,所以,要求您的网络环境可以直接访问kong admin api。这么设计是想方便大家,不用再单独部署一套Kong的UI,如果你只是想找个管理界面,不想对这个项目进行二次开发,那么,只需要使用我部署的 demo。除了你的kong admin api接口,不会再请求其他接口,所以你可以放心,我不会保存你的任何信息。

最近在学习Kong,一个基于Nginx的Api网关,发现网上还没有中文文档,所以打算每天抽点时间,把官方文档翻译一下,方便对Kong感兴趣的国内开发者,目前翻译工作刚刚开始,持续更新。文档链接 Kong网关中文文档

大部分路由器(包括非智能路由)都支持ddns,一般是集成花生壳、公云等有限的几家服务商。直接使用路由器集成的ddns功能,优点是简单,缺点就是慢。因为DDNS都是用服务商提供的域名,如果要使用我们自己的域名,需要cname到服务商的域名,这里就存在二次解析,更别说免费DDNS本身速度慢了。 现在的智能路由器都是基于linux的,我们完全可以写一个脚本检测外网ip,在路由器外网ip变化时,去DNS服务提供商直接更改dns设置新的IP,实现DDNS功能。 准备环境:

  • 路由器:小米路由3G 需root,否则登不上ssh, ip 192.168.0.1
  • DNS服务商:dnspod

理论上所有openwrt路由都支持,因为下面的脚本没用到小米路由的特性,都是linux上的命令,但我没有测其他路由器。 dnspod开放了api,可以调接口更新记录,现在已经被腾讯收购,也可以用腾讯的api,但腾讯的api比较复杂,反正我没调通。其他的像阿里云也开放了云解析接口,有需要的同学可以自己研究。 重点不在脚本,而在于思路:

  • linux 定时任务,每分钟执行一次脚本
  • 脚本访问外网指定服务器,获取当前外网ip地址,比较上次获取的外网ip地址,如果不一致,则调dns系统的api更新记录

ddns 脚本内容:

#!/bin/sh
oldIPFile=/tmp/oldip.txt
login_token=xxxxxxx
domain=pocketdigi.com
record_id=xxxxxxx
sub_domain=test

updateIp(){
  result=$(curl -s -d "login_token=$login_token&format=json&domain=$domain&record_id=$record_id&sub_domain=$sub_domain&value=$myip&record_type=A&record_line=默认" https://dnsapi.cn/Record.Modify)
  grepResult=$(echo $result | grep "\"code\":\"1\"")
  if [[ "$grepResult" != "" ]]
   then
       echo '更新成功'
       echo "$myip" > $oldIPFile
   else
       echo '更新失败'
  fi
}

myip=$(curl -s http://myip.dnsomatic.com/)
echo "当前ip:$myip"


if [ ! -f "$oldIPFile" ]; then
  echo "文件不存在,更新"
  updateIp;
else
  oldip=$(cat $oldIPFile)
  echo "旧IP:$oldip"
  if [ "$myip" = "$oldip" ]; then
    echo "当前IP与旧IP相同,不更新"
  else
    echo "当前IP与旧IP不同,更新"
    updateIp
  fi
fi

login_token需要登录dnspod获取,record_id可以使用chrome,在dnspod后台编辑保存那条记录时抓包找到。 使用scp将脚本拷到路由器上的/data目录,小米路由很多目录是只读的,写不进去 ssh登录路由器:

ssh root@192.168.0.1

密码需要到小米路由官网找 给ddns脚本增加可执行权限

chmod +x /data/ddns

添加定时任务

crontab -e

在末尾添加

* * * * * /data/ddns

大功告成!

kibana默认的地图大部分都是英文,对国人不太友好。Kibana使用的是tilemap瓦片地图,支持配置其他地图,其标准与google的tilemap相同,采用这一标准的还有高德。所以,我们可以直接换成google或高德。 打开config下的kibana.yml,在文件底部添加:

    tilemap.url: 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}'
    #tilemap.url: 'http://mt2.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}'
    tilemap.options.maxZoom: 18

用google还是高德随意,google.cn在国内还是可以访问的,tilemap.options.maxZoom配置的是最大缩放级别,默认只能缩放到区级。 重启kibana,6.3.1实测有效。

已经修改了/etc/security/limits.conf ,把数值加到65536,用elasticsearch用户启动,一切正常,但一旦用systemctl启动,还是报max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536] 而且,我的配置文件已经指定使用elasticsearch用户,诡异的错误。 其实出现这个问题,原因在于/etc/security/limits.conf里的配置只针对PAM认证登录用户有效,而Systemd有自己的一套配置。全局配置在/etc/systemd/system.conf和/etc/systemd/user.conf,也可以对单个服务做配置,所以,elasticsearch的脚本要做下修改:

[Unit]
Description=Elasticsearch

[Service]
Environment=JAVA_HOME=/usr/local/jdk1.8.0_171
LimitCORE=infinity
LimitNOFILE=65536
LimitNPROC=65536
ExecStart=/usr/local/elasticsearch-6.3.1/bin/elasticsearch
User=elasticsearch
Group=elasticsearch

[Install]
WantedBy=multi-user.target

我们的app是全屏沉浸式的,发现activity在设置了全屏后,弹出dialog底部会跳出导航栏虚拟键。具体原因是因为Dialog的Window抢走了焦点,Window 中的 DecorView 状态改变导致了退出。 解决方法,在Dialog中:

   private void fullScreenImmersive(View view) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_FULLSCREEN;
            view.setSystemUiVisibility(uiOptions);
        }
    }

    @Override
    public void show() {
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
        super.show();
        fullScreenImmersive(getWindow().getDecorView());
        this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
    }

为什么要建docker私服

  • 官服在国外,速度慢
  • 创建的镜像是私有的,不想公开传到外部服务器上

Sonatype Nexus介绍

Sonatype Nexus是一个仓库管理软件,支持Maven、Docker、Bower、PyPI、Yum等类型仓库。使用Maven管理依赖的Java程序员一定不陌生,搭建Maven私服基本是用这个。注意:3.x版本才支持docker。 今天我们就用Nexus作Docker的私服,管理我们自己的私有镜像。

Sonatype Nexus安装

很简单,下载,解压,我的路径是
/usr/local/nexus-3.11.0-01
创建开机启动脚本
vim /etc/systemd/system/nexus.service
内容如下:

[Unit]
Description=nexus service
After=network.target

[Service]
Type=forking
LimitNOFILE=65536
ExecStart=/usr/local/nexus-3.11.0-01/bin/nexus start
ExecStop=/usr/local/nexus-3.11.0-01/bin/nexus stop
Restart=on-abort

[Install]
WantedBy=multi-user.target

设置开机启动
systemctl enable nexus
启动
systemctl start nexus nexus默认端口是8081, 现在打开浏览器,访问http://ip:8081, 应该能看到如下界面
 点击右上角Sign in,账号admin 密码admin123,登录
 点击admin ,把默认的密码改掉,安装完成。

创建仓库

点击顶部配置图标,切到配置页面,左侧菜单选Repositories, 打开仓库配置,点击Create repository 创建仓库。
 我之前已经创建好,配置如下图
 注意,这里HTTP设置了一个10008端口,仅供docker使用,找个不冲突的就行。

docker配置

docker仓库默认需要https支持,但nexus没有配ssl,需要将服务器加到insecure-registries。
vim /etc/docker/daemon.json

{
  "registry-mirrors": ["https://registry.docker-cn.com"],
  "insecure-registries":["192.168.0.201:10008"]
}

我的nexus部署在192.168.0.201 后面的端口10008与创建仓库时对应。 登录仓库:
docker login 192.169.0.201:10008
按提示输入nexus的账号密码。登录一次以后,会自动保存,以后pull/push都不需要再登录。

docker 提交镜像

  1. 将正在运行的container打包成image

    如图,nginx2容器基于nginx镜像,但是改了一些配置, 现在我们将其打包成image
    docker commit -m "nginx modified" -a "Exception" cb4cbbcde646 nginx-modified -m 描述
    -a 作者
    cb4cbbcde646 container id
    nginx-modified 生成的image名
    现在再看镜像列表:
    
    发现我们刚刚commit的image已经在里面了。

  2. 给image打标签
    docker tag f3b408f36cf7 192.168.0.201:10008/nginx-modified f3b408f36cf7 image id
    192.168.0.201:10008/nginx-modified 仓库地址和保存路径

  3. 推送镜像
    docker push 192.168.0.201:10008/nginx-modified

  4. 下载镜像
    在另一台服务器上,如果要下载镜像,重复上面的docker配置步骤,然后pull
    docker pull 192.168.0.201:10008/nginx-modified