Skip to content

Commit

Permalink
optimize lua-script for ensureNotExpired
Browse files Browse the repository at this point in the history
optimize u-test for Discovery
optimize - update the cache of instance in a fine-grained way
add README.zh-CN.md
  • Loading branch information
Ahoo-Wang committed May 8, 2021
1 parent b2273fc commit 09ba679
Show file tree
Hide file tree
Showing 22 changed files with 507 additions and 86 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Govern Service On Redis (Service Discovery and Configuration Service)

> [中文文档](./README.zh-CN.md)
*Govern Service* is a lightweight, low-cost service registration, service discovery, and configuration service SDK. By
using Redis in the existing infrastructure (I believe you have already deployed Redis), it doesn’t need to bring extra
to the operation and maintenance deployment. Cost and burden. With the high performance of Redis, *Govern Service*
Expand All @@ -11,7 +13,7 @@ process cache refresh, with unparalleled QPS performance and real-time consisten
### Gradle

``` kotlin
val governVersion = "0.8.0";
val governVersion = "0.8.2";
implementation("me.ahoo.govern:spring-cloud-starter-config:${governVersion}")
implementation("me.ahoo.govern:spring-cloud-starter-discovery:${governVersion}")
```
Expand All @@ -28,7 +30,7 @@ process cache refresh, with unparalleled QPS performance and real-time consisten
<modelVersion>4.0.0</modelVersion>
<artifactId>demo</artifactId>
<properties>
<govern.version>0.8.0</govern.version>
<govern.version>0.8.2</govern.version>
</properties>

<dependencies>
Expand Down
173 changes: 173 additions & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# 基于 Redis 的服务治理平台(服务注册/发现 & 配置中心)

*Govern Service* 是一个轻量级、低成本的服务注册、服务发现、 配置服务 SDK,通过使用现有基础设施中的 Redis (相信你已经部署了Redis),不用给运维部署带来额外的成本与负担。 借助于 Redis 的高性能, *
Govern Service* 提供了超高TPS&QPS。*Govern Service* 结合本地进程缓存策略 + *Redis PubSub*,实现实时进程缓存刷新,兼具无与伦比的QPS性能、进程缓存与 Redis 的实时一致性。

## 安装

### Gradle

``` kotlin
val governVersion = "0.8.2";
implementation("me.ahoo.govern:spring-cloud-starter-config:${governVersion}")
implementation("me.ahoo.govern:spring-cloud-starter-discovery:${governVersion}")
```

### Maven

```xml
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>
<artifactId>demo</artifactId>
<properties>
<govern.version>0.8.2</govern.version>
</properties>

<dependencies>
<dependency>
<groupId>me.ahoo.govern</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>${govern.version}</version>
</dependency>
<dependency>
<groupId>me.ahoo.govern</groupId>
<artifactId>spring-cloud-starter-discovery</artifactId>
<version>${govern.version}</version>
</dependency>
</dependencies>

</project>
```

### bootstrap.yml (Spring-Cloud-Config)

```yaml
spring:
application:
name: govern-rest-api
cloud:
govern:
namespace: dev
config:
config-id: ${spring.application.name}.yml
redis:
mode: standalone
url: redis://localhost:6379
```
## REST-API Server (``Optional``)
```shell
bin/rest-api
```

> http://localhost:8080/swagger-ui/index.html#/
### Namespace

![rest-api-namespace](./docs/rest-api-namespace.png)

- /v1/namespaces
- GET
- /v1/namespaces/{namespace}
- PUT
- GET
- /v1/namespaces/current
- GET
- /v1/namespaces/current/{namespace}
- PUT

### Config

![rest-api-config](./docs/rest-api-config.png)

- /v1/namespaces/{namespace}/configs
- GET
- /v1/namespaces/{namespace}/configs/{configId}
- GET
- PUT
- DELETE
- /v1/namespaces/{namespace}/configs/{configId}/versions
- GET
- /v1/namespaces/{namespace}/configs/{configId}/versions/{version}
- GET
- /v1/namespaces/{namespace}/configs/{configId}/to/{targetVersion}
- PUT

### Service

![rest-api-service](./docs/rest-api-service.png)

- /v1/namespaces/{namespace}/services/
- GET
- /v1/namespaces/{namespace}/services/{serviceId}/instances
- GET
- PUT
- /v1/namespaces/{namespace}/services/{serviceId}/instances/{instanceId}
- DELETE
- /v1/namespaces/{namespace}/services/{serviceId}/instances/{instanceId}/metadata
- PUT

## JMH 基准测试

- The development notebook : MacBook Pro (M1)
- All benchmark tests are carried out on the development notebook.
- Deploying Redis with docker on the development notebook.

``` shell
gradle jmh
```

### ConfigService

```
# JMH version: 1.28
# VM version: JDK 11.0.11, OpenJDK 64-Bit Server VM, 11.0.11+9-LTS
# VM invoker: /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home/bin/java
# VM options: -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/Users/ahoo/govern-service/config/build/tmp/jmh -Duser.country=CN -Duser.language=zh -Duser.variant
# Blackhole mode: full + dont-inline hint
# Warmup: 1 iterations, 10 s each
# Measurement: 1 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 50 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
Benchmark Mode Cnt Score Error Units
ConsistencyRedisConfigServiceBenchmark.getConfig thrpt 555275866.836 ops/s
RedisConfigServiceBenchmark.getConfig thrpt 57397.188 ops/s
RedisConfigServiceBenchmark.setConfig thrpt 56882.673 ops/s
```

### ServiceDiscovery

```
# JMH version: 1.29
# VM version: JDK 11.0.11, OpenJDK 64-Bit Server VM, 11.0.11+9-LTS
# VM invoker: /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home/bin/java
# VM options: -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/Users/ahoo/work/ahoo-git/govern-service/discovery/build/tmp/jmh -Duser.country=CN -Duser.language=zh -Duser.variant
# Blackhole mode: full + dont-inline hint
# Warmup: 1 iterations, 10 s each
# Measurement: 1 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 50 threads, will synchronize iterations
# Benchmark mode: Throughput, ops/time
Benchmark Mode Cnt Score Error Units
ConsistencyRedisServiceDiscoveryBenchmark.getInstances thrpt 567329996.255 ops/s
ConsistencyRedisServiceDiscoveryBenchmark.getServices thrpt 1929377291.635 ops/s
RedisServiceDiscoveryBenchmark.getInstances thrpt 43760.035 ops/s
RedisServiceDiscoveryBenchmark.getServices thrpt 60953.971 ops/s
RedisServiceRegistryBenchmark.deregister thrpt 63133.011 ops/s
RedisServiceRegistryBenchmark.register thrpt 53957.797 ops/s
RedisServiceRegistryBenchmark.renew thrpt 67116.116 ops/s
```

## TODO

1. Dashboard
2. Grayscale Publishing
74 changes: 74 additions & 0 deletions core/src/test/java/me/ahoo/govern/core/util/ScriptTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package me.ahoo.govern.core.util;

import io.lettuce.core.RedisClient;
import io.lettuce.core.ScriptOutputType;
import io.lettuce.core.api.sync.RedisCommands;
import me.ahoo.govern.core.TestRedisClient;
import org.junit.jupiter.api.*;

import java.util.Objects;

/**
* @author ahoo wang
*/
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ScriptTest {
private RedisClient redisClient;
private RedisCommands<String, String> redisCommands;

@BeforeAll
private void init() {
redisClient = TestRedisClient.createClient();
redisCommands = redisClient.connect().sync();
}

@Test
void testReturnBoolean() {
Boolean negativeOne = redisCommands.eval("return -1;", ScriptOutputType.BOOLEAN);
Assertions.assertFalse(negativeOne);
Boolean zero = redisCommands.eval("return 0;", ScriptOutputType.BOOLEAN);
Assertions.assertFalse(zero);
Boolean one = redisCommands.eval("return 1;", ScriptOutputType.BOOLEAN);
Assertions.assertTrue(one);
Boolean two = redisCommands.eval("return 2;", ScriptOutputType.BOOLEAN);
Assertions.assertFalse(two);

Boolean fa = redisCommands.eval("return false;", ScriptOutputType.BOOLEAN);
Assertions.assertFalse(fa);
Boolean tr = redisCommands.eval("return true;", ScriptOutputType.BOOLEAN);
Assertions.assertTrue(tr);
}

@Test
void testReturnLong() {
Long negativeOne = redisCommands.eval("return -1;", ScriptOutputType.INTEGER);
Assertions.assertEquals(-1, negativeOne);
Long zero = redisCommands.eval("return 0;", ScriptOutputType.INTEGER);
Assertions.assertEquals(0, zero);
Long one = redisCommands.eval("return 1;", ScriptOutputType.INTEGER);
Assertions.assertEquals(1, one);
Long two = redisCommands.eval("return 2;", ScriptOutputType.INTEGER);
Assertions.assertEquals(2, two);
}

@Test
void testReturnStatus() {
Object status = redisCommands.eval("return 'ok';", ScriptOutputType.STATUS);

Assertions.assertEquals("ok", status);
}

@Test
void testReturnValue() {
Object val = redisCommands.eval("return 'ok';", ScriptOutputType.VALUE);

Assertions.assertEquals("ok", val);
}

@AfterAll
private void destroy() {
if (Objects.nonNull(redisClient)) {
redisClient.shutdown();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package me.ahoo.govern.discovery;

import java.util.List;
Expand All @@ -22,6 +19,6 @@ public interface ServiceDiscovery {

CompletableFuture<ServiceInstance> getInstance(String namespace, String serviceId, String instanceId);

CompletableFuture<Integer> getInstanceTtl(String namespace, String serviceId, String instanceId);
CompletableFuture<Long> getInstanceTtl(String namespace, String serviceId, String instanceId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
* @author ahoo wang
*/
public class ServiceInstance extends Instance {

public static final ServiceInstance NOT_FOUND = new ServiceInstance();
private int weight = 1;
private boolean ephemeral = true;
private int ttlAt = -1;
private long ttlAt = -1;
private Map<String, String> metadata = new LinkedHashMap<>();

public int getWeight() {
Expand All @@ -40,11 +40,11 @@ public void setMetadata(Map<String, String> metadata) {
this.metadata = metadata;
}

public int getTtlAt() {
public long getTtlAt() {
return ttlAt;
}

public void setTtlAt(int ttlAt) {
public void setTtlAt(long ttlAt) {
this.ttlAt = ttlAt;
}

Expand Down
Loading

0 comments on commit 09ba679

Please sign in to comment.