青云开发

学习、记录、总结、侃大山

必要条件

  • 一台可通过公网地址访问的服务器

    服务器可在阿里云或腾讯云购买。

  • 一个具有支付接口权限的公众号

    公众号自然是在 ‘微信公众平台’ 申请。具有支付权限的公众号得注册为企业级公众号(或称为服务号),并且通过了企业认证。企业认证需要机关单位或企业门店的 ‘营业执照’ 。在公司的话可使用公司营业执照。如果是个人,除了借别人的就只能自己去办一个了。(我就是自己去申请办理了 “个体工商户营业执照”。办理这个营业执照需要房屋或经营场所的产权使用证明和身份证。房屋使用证明可以是购房合同,和租赁合同,或产权证和产权所有方手写的一张授权使用证明。办理地点就在经营场所所在当地的市场监督管理局,一般一周就能办理下来。办理下来后根据规定得去当地的税务局办理税务登记手续,然后就可以去正规的刻章店刻章了,这时候你这个个体户也就是小企业可以开张了。公众号有了营业执照和公章就足以办理企业认证了。当然如果你办公场地装修好了也有人上岗办公了那么这个时候可以去银行开通一个对公账户。微信支付可用的上,没有的话也没关系微信支付也可以填写私人银行账户。另外:办理税务登记后记得每个季度去办理税务申报,可在网上办理也可直接去税务局办理。逾期没办的税务局会打电话给你,有可能会影响企业信誉)

    听说前段时间微信给个人公众号也开放的支付功能,我还没去看相关文档。

  • 一个已经通过了备案的域名

    域名和服务器一样可在阿里或腾讯购买。(不过我忘了域名备案需要些什么东西了)

  • 具有一定的前后端开发能力以及服务器搭建能力

实现步骤

首要目标

在微信的小程序或公众号内的支付场景中,除了业务上的一些交互外往往最终付款的时候我们就是通过一个按钮 “结算” 或 “付款” 来唤起支付页面。然后输入密码,成功后就跳转到支付成功的页面。事实上也是如此。通过微信开放文档得知唤起支付页面就是下面这段 js 代码

1
2
3
4
5
6
7
8
9
10
11
//文档地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#58
wx.chooseWXPay({
timestamp: 0, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: '', // 支付签名随机串,不长于 32 位
package: '', // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: '', // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: '', // 支付签名
success: function (res) {
// 支付成功后的回调函数(跳转到支付成功页面等操作)
}
});

我们的目标就是要这段代码能够完美的得到执行。

通过阅读文档发现这段 js 需要的参数package prepay_id 得通过统一下单接口才能拿到。而调用统一下单接口又有一个关键参数 openId 而这个 openId 得通过网页授权才能拿到。

网页授权的前提又必须开启公众号的开发者模式。开启开发者模式可参看本博客文章 微信公众号配置服务器

阅读全文 »

前言

程序开发者在没有服务器的情况下,可把自己的电脑当作服务器提供给外网访问。这里可以通过路由器设置来实现(或许还有其它的方式)。不过这种方式需要满足三个条件。

条件

  1. 具备路由器的操作权限(知道路由器的登录名和密码)
  2. 路由器具备虚拟服务器设置的功能
  3. 路由器拨号上网得到的 ip 是公网 ip

开始

  1. 登录路由器查看 ip

    image-20210222161027315

    查看公网 ip 直接 百度 ip 即可得到。

    image-20210222161223082

    这里如果路由器 ip 不等于公网 ip 那么得打电话给运营商设置了。我自己的就是这样。(客服帮助设置后。路由器重新设置拨号上网后即可)

  2. 配置虚拟服务器

    我家的 tp-link 路由是这样的

    image-20210222160811607

    image-20210222161758009

    没有就添加一条。常用服务器选 http 就好。

    外部端口:根据自己的情况填写。

    内部端口:电脑上启动的服务的端口

    ip 地址:填写电脑的 IP 地址。可通过 cmd 执行 ipconfig 查询到。

    协议类型:tcp/udp 所有

    阅读全文 »

jwt 介绍

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

硬翻译:JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑而独立的方法,用于在各方之间安全地将信息作为JSON对象传输。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公用/专用密钥对对JWT进行签名。

Although JWTs can be encrypted to also provide secrecy between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.

硬翻译:尽管可以对JWT进行加密以提供双方之间的保密性,但我们将重点关注已签名的令牌。签名的令牌可以验证其中包含的声明的完整性,而加密的令牌则将这些声明隐藏在其他方的面前。当使用公钥/私钥对对令牌进行签名时,签名还证明只有持有私钥的一方才是对其进行签名的一方。

—— jwt 官网介绍

jwt 能做的事

  • Authorization: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token. Single Sign On is a feature that widely uses JWT nowadays, because of its small overhead and its ability to be easily used across different domains.

    授权:这是使用JWT的最常见方案。一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。单一登录是当今广泛使用JWT的一项功能,因为它的开销很小并且可以在不同的域中轻松使用。

  • Information Exchange: JSON Web Tokens are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn’t been tampered with.

    信息交换:JSON Web令牌是在各方之间安全传输信息的一种好方法。因为可以对JWT进行签名(例如,使用公钥/私钥对),所以您可以确保发件人是他们所说的人。此外,由于签名是使用标头和有效负载计算的,因此您还可以验证内容是否未被篡改。

jwt 组成结构

  • Header
  • Payload
  • Signature

整体看起来像:

1
xxxxx.yyyyy.zzzzz

header 通常由两部分组成:令牌的类型为JWT,以及所使用的签名算法,例如HMAC SHA256或RSA。

例如:

1
2
3
4
{
"alg": "HS256",
"typ": "JWT"
}

此JSON被Base64Url编码以形成JWT的第一部分。

payload 令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的声明。共有三种类型的索赔:注册,公共和私人索赔。

例如:

1
2
3
4
5
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}

此JSON被Base64Url编码以形成JWT的第二部分。

Signature 要创建签名部分,您必须获取编码的标头,编码的有效载荷,机密,标头中指定的算法,并对其进行签名。

例如,如果要使用HMAC SHA256算法,则将通过以下方式创建签名

1
2
3
4
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
阅读全文 »

下载

linux 上执行:

1
2
3
4
5
6
7
8
9
10
11
12
[root@iZx068ismxxjaoZ src]#  wget http://download.redis.io/releases/redis-6.0.6.tar.gz
--2020-12-17 12:58:12-- http://download.redis.io/releases/redis-6.0.6.tar.gz
Resolving download.redis.io (download.redis.io)... 45.60.125.1
Connecting to download.redis.io (download.redis.io)|45.60.125.1|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2228781 (2.1M) [application/octet-stream]
Saving to: ‘redis-6.0.6.tar.gz’

100%[========================================================================================================================>] 2,228,781 24.6KB/s in 69s

2020-12-17 12:59:25 (31.6 KB/s) - ‘redis-6.0.6.tar.gz’ saved [2228781/2228781]

解压

1
[root@iZx068ismxxjaoZ src]# tar -xzf redis-6.0.6.tar.gz 

编译(源码)

1
2
[root@iZx068ismxxjaoZ src]# cd redis-6.0.6
[root@iZx068ismxxjaoZ redis-6.0.6]# make

报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
......
^
server.c:5212:31: error: ‘struct redisServer’ has no member named ‘server_cpulist’
redisSetCpuAffinity(server.server_cpulist);
^
server.c: In function ‘hasActiveChildProcess’:
server.c:1480:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
server.c: In function ‘allPersistenceDisabled’:
server.c:1486:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
server.c: In function ‘writeCommandsDeniedByDiskError’:
server.c:3826:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
server.c: In function ‘iAmMaster’:
server.c:5000:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
make[1]: *** [server.o] Error 1
make[1]: Leaving directory `/usr/local/src/redis-6.0.6/src'
make: *** [all] Error 2

阅读全文 »

前言

在微信公众号(服务号)开发的准备阶段需要我们配置自己的服务器。

image-20201217131942035

文档地址:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html

下载运行官方示例

https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Message_Encryption/Message_encryption_and_decryption.html

image-20201202171753034

下载示例代码后解压如下:

image-20201202172231504

把 src 的代码复制到项目并解决完包路径问题后运行 demo 的 main 方法。提示如下

1
2
3
4
5
6
7
8
9
D:\Java\jdk1.8.0_144\bin\java.exe "-javaagent:D:\Program Files\ideaIU-2019.2win\lib\idea_rt.jar=1346:D:\Program Files\ideaIU-2019.2win\bin" -Dfile.encoding=UTF-8 -classpath "D:\Java\jdk1.8.0_144\jre\lib\charsets.jar;D:\Java\jdk1.8.0_144\jre\lib\deploy.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\dnsns.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar;D:\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar;D:\Java\jdk1.8.0_144\jre\lib\javaws.jar;D:\Java\jdk1.8.0_144\jre\lib\jce.jar;D:\Java\jdk1.8.0_144\jre\lib\jfr.jar;D:\Java\jdk1.8.0_144\jre\lib\jfxswt.jar;D:\Java\jdk1.8.0_144\jre\lib\jsse.jar;D:\Java\jdk1.8.0_144\jre\lib\management-agent.jar;D:\Java\jdk1.8.0_144\jre\lib\plugin.jar;D:\Java\jdk1.8.0_144\jre\lib\resources.jar;D:\Java\jdk1.8.0_144\jre\lib\rt.jar;D:\IdeaProjects\qingyun\plantform\target\classes;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\boot\spring-boot-starter-data-jdbc\2.4.0\spring-boot-starter-data-jdbc-2.4.0.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\data\spring-data-jdbc\2.1.1\spring-data-jdbc-2.1.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\data\spring-data-relational\2.1.1\spring-data-relational-2.1.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\data\spring-data-commons\2.4.1\spring-data-commons-2.4.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\spring-tx\5.3.1\spring-tx-5.3.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\spring-context\5.3.1\spring-context-5.3.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\spring-beans\5.3.1\spring-beans-5.3.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\boot\spring-boot-starter-jdbc\2.4.0\spring-boot-starter-jdbc-2.4.0.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\boot\spring-boot-starter\2.4.0\spring-boot-starter-2.4.0.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\boot\spring-boot-starter-logging\2.4.0\spring-boot-starter-logging-2.4.0.jar;D:\Program Files\apache-maven-3.5.3\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;D:\Program Files\apache-maven-3.5.3\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;D:\Program Files\apache-maven-3.5.3\repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;D:\Program Files\apache-maven-3.5.3\repository\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;D:\Program Files\apache-maven-3.5.3\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;D:\Program Files\apache-maven-3.5.3\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\Program Files\apache-maven-3.5.3\repository\org\yaml\snakeyaml\1.27\snakeyaml-1.27.jar;D:\Program Files\apache-maven-3.5.3\repository\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\spring-jdbc\5.3.1\spring-jdbc-5.3.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\boot\spring-boot-starter-web\2.4.0\spring-boot-starter-web-2.4.0.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\boot\spring-boot-starter-json\2.4.0\spring-boot-starter-json-2.4.0.jar;D:\Program Files\apache-maven-3.5.3\repository\com\fasterxml\jackson\core\jackson-databind\2.11.3\jackson-databind-2.11.3.jar;D:\Program Files\apache-maven-3.5.3\repository\com\fasterxml\jackson\core\jackson-annotations\2.11.3\jackson-annotations-2.11.3.jar;D:\Program Files\apache-maven-3.5.3\repository\com\fasterxml\jackson\core\jackson-core\2.11.3\jackson-core-2.11.3.jar;D:\Program Files\apache-maven-3.5.3\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.3\jackson-datatype-jdk8-2.11.3.jar;D:\Program Files\apache-maven-3.5.3\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.3\jackson-datatype-jsr310-2.11.3.jar;D:\Program Files\apache-maven-3.5.3\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.3\jackson-module-parameter-names-2.11.3.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\boot\spring-boot-starter-tomcat\2.4.0\spring-boot-starter-tomcat-2.4.0.jar;D:\Program Files\apache-maven-3.5.3\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.39\tomcat-embed-core-9.0.39.jar;D:\Program Files\apache-maven-3.5.3\repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;D:\Program Files\apache-maven-3.5.3\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.39\tomcat-embed-websocket-9.0.39.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\spring-web\5.3.1\spring-web-5.3.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\spring-webmvc\5.3.1\spring-webmvc-5.3.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\spring-aop\5.3.1\spring-aop-5.3.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\spring-expression\5.3.1\spring-expression-5.3.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\mybatis\spring\boot\mybatis-spring-boot-starter\2.1.4\mybatis-spring-boot-starter-2.1.4.jar;D:\Program Files\apache-maven-3.5.3\repository\org\mybatis\spring\boot\mybatis-spring-boot-autoconfigure\2.1.4\mybatis-spring-boot-autoconfigure-2.1.4.jar;D:\Program Files\apache-maven-3.5.3\repository\org\mybatis\mybatis\3.5.6\mybatis-3.5.6.jar;D:\Program Files\apache-maven-3.5.3\repository\org\mybatis\mybatis-spring\2.0.6\mybatis-spring-2.0.6.jar;D:\Program Files\apache-maven-3.5.3\repository\org\thymeleaf\extras\thymeleaf-extras-springsecurity5\3.0.4.RELEASE\thymeleaf-extras-springsecurity5-3.0.4.RELEASE.jar;D:\Program Files\apache-maven-3.5.3\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\boot\spring-boot-devtools\2.4.0\spring-boot-devtools-2.4.0.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\boot\spring-boot\2.4.0\spring-boot-2.4.0.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\boot\spring-boot-autoconfigure\2.4.0\spring-boot-autoconfigure-2.4.0.jar;D:\Program Files\apache-maven-3.5.3\repository\mysql\mysql-connector-java\8.0.22\mysql-connector-java-8.0.22.jar;D:\Program Files\apache-maven-3.5.3\repository\org\projectlombok\lombok\1.18.16\lombok-1.18.16.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\spring-core\5.3.1\spring-core-5.3.1.jar;D:\Program Files\apache-maven-3.5.3\repository\org\springframework\spring-jcl\5.3.1\spring-jcl-5.3.1.jar;D:\Program Files\apache-maven-3.5.3\repository\commons-codec\commons-codec\1.13\commons-codec-1.13.jar" com.wzy.plantform.weixin.demo.Program
Exception in thread "main" java.lang.IllegalArgumentException: Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible value
at org.apache.commons.codec.binary.Base64.validateCharacter(Base64.java:798)
at org.apache.commons.codec.binary.Base64.decode(Base64.java:477)
at org.apache.commons.codec.binary.BaseNCodec.decode(BaseNCodec.java:411)
at org.apache.commons.codec.binary.BaseNCodec.decode(BaseNCodec.java:395)
at org.apache.commons.codec.binary.Base64.decodeBase64(Base64.java:694)
at com.wzy.plantform.weixin.aes.WXBizMsgCrypt.<init>(WXBizMsgCrypt.java:62)
at com.wzy.plantform.weixin.demo.Program.main(Program.java:32)
阅读全文 »

引言

在微服务架构下,推荐每个服务都有自己独立的数据库、缓存、搜索等,这样做的优点是能够让服务之间的耦合度降低,同时可以让不同的服务根据不同的业务需求选择自己合适的存储方式。搜索服务可以用 Elasticsearch,日志服务可以用 Mongodb,业务数据可以用 MYSQL 。缺点就是对于事务的处理比较麻。所以我们尽量避免分布式事务,采用合理的设计。

——《spring cloud 微服务 入门、进阶与实战》

存储选型

关于数据库的选择每个公司都不太一样,说说我的选择吧。业务数据肯定是用 MYSQL,如果资金允许也可以用 Oracle;搜索服务用 Elasticsearch来构建;大数据量的基础数据,采用 Mongodb存储,缓存用 Redis 即可。一个中小型的互联网公司用这些组件基本上就足够了。微服务的好处在这里就体现出来了,每个服务都可以根据自己的业务选择最合适的存储方式。

——《spring cloud 微服务 入门、进阶与实战》

Mongodb

集成 Spring Data Mongodb

  • 在 spring boot 中集成 mongodb 只需要加入对应的 starter 就可以了,非常方便。
1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
  • 配置数据源
1
2
3
4
5
6
# mongodb
spring.data.mongodb.database=test
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
#spring.data.mongodb.username=xxx
#spring.data.mongodb.password=xxx

添加数据操作

阅读全文 »

admin server

  • 建立一个 spring boot 项目并添加 admin 依赖
1
2
3
4
5
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.2.2</version>
</dependency>
  • 启动类加上注解:
1
2
3
4
5
6
7
8
@EnableAdminServer//开启 admin server
@SpringBootApplication
public class SpringcloudAdminServiceApplication {

public static void main(String[] args) {
SpringApplication.run(SpringcloudAdminServiceApplication.class, args);
}
}
  • 端口:
1
server.port=8091

启动项目 访问:http://localhost:8091/

image-20200517230826809

阅读全文 »

引言

在微服务架构下,服务之间的调用关系越来越复杂,通过 Zuul 转发到具体的业务接 ,一个接口中会涉及多个微服务的交互,只要其中某个服务出现问题,整个请求都将失败。这个时候我们要想快速定位到问题所在,就需要用到链路跟踪了。每个请求都是一条完整的调用链,通过调用链我们可以清楚地知道这个请求经过了哪些服务,在哪个服务上耗时多长时间,进而达到快速定位问题的目的。

为了解决上面提到的问题, Spring Cloud Sleuth为我们提供了完整的解决方案。本章我们将学习如何使用 Spring Cloud Sleuth来构建分布式链路跟踪功能。

——《spring cloud 微服务 入门、进阶与实战》第197页

Sleuth 官网:https://spring.io/projects/spring-cloud-sleuth#overview

spring cloud 集成 Sleuth

  • 给调用链中所有服务加上依赖
1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
  • 代码中打印日志:
1
logger.info("method call/hello be called.....");

介绍

Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

—— Apollo官方WIKI

gitHub:Apollo

特点

正是基于配置的特殊性,所以Apollo从设计之初就立志于成为一个有治理能力的配置发布平台,目前提供了以下的特性:

  • 统一管理不同环境、不同集群的配置
    • Apollo提供了一个统一界面集中式管理不同环境(environment)、不同集群(cluster)、不同命名空间(namespace)的配置。
    • 同一份代码部署在不同的集群,可以有不同的配置,比如zookeeper的地址等
    • 通过命名空间(namespace)可以很方便地支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖
  • 配置修改实时生效(热发布)
    • 用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序
  • 版本发布管理
    • 所有的配置发布都有版本概念,从而可以方便地支持配置的回滚
  • 灰度发布
    • 支持配置的灰度发布,比如点了发布后,只对部分应用实例生效,等观察一段时间没问题后再推给所有应用实例
  • 权限管理、发布审核、操作审计
    • 应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误。
    • 所有的操作都有审计日志,可以方便地追踪问题
  • 客户端配置信息监控
    阅读全文 »
0%