状态管理
状态管理(State Management)使用键值对作为存储机制,可以轻松的使长时运行、高可用的有状态服务和无状态服务共同运行在我们的服务中。
我们的服务可以利用 Dapr 的状态管理 API 在状态存储组件中保存、读取和查询键值对。
状态存储组件是可插拔的,目前支持使用 Azure CosmosDB、 Azure SQL Server、 PostgreSQL,、AWS DynamoDB、Redis 作为状态存储介质。
编写示例代码
创建一个 SpringBoot 项目,命名为:state-management
,该项目的状态管理调用过程如下图:
在state-management
该项目的pom.xml
文件中添加如下依赖:
<dependency>
<groupId>io.dapr</groupId>
<artifactId>dapr-sdk-springboot</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
复制代码
注入一个DaprClient
的 bean:
@Configuration
public class DaprConfig {
private static final DaprClientBuilder BUILDER = new DaprClientBuilder();
@Bean
public DaprClient buildDaprClient() {
return BUILDER.build();
}
}
复制代码
state-management
项目中一共有 3 个接口:
save
:保存状态
get
:读取状态
delete
:删除状态
具体源码如下:
package one.more.society.state.management;
import io.dapr.client.DaprClient;
import io.dapr.client.domain.State;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class StateManagementController {
@Autowired
private DaprClient client;
private static final String STATE_STORE_NAME = "statestore";
private static final String STATE_STORE_KEY = "one.more.society";
/**
* 保存状态
*
* @param value value
* @return
*/
@RequestMapping(value = "/save", method = RequestMethod.GET)
public StateResponse save(String value) {
log.info("save - value:{}", value);
client.saveState(STATE_STORE_NAME, STATE_STORE_KEY, value).block();
StateResponse response = new StateResponse();
response.setCode(1);
response.setStatus("save");
response.setValue(value);
return response;
}
/**
* 读取状态
*
* @return StateResponse
*/
@RequestMapping(value = "/get", method = RequestMethod.GET)
public StateResponse get() {
log.info("get");
State<String> value = client.getState(STATE_STORE_NAME, STATE_STORE_KEY, String.class).block();
log.info("value: {}", value.getValue());
StateResponse response = new StateResponse();
response.setCode(1);
response.setStatus("get");
response.setValue(value.getValue());
return response;
}
/**
* 删除状态
*
* @return
*/
@RequestMapping(value = "/delete", method = RequestMethod.GET)
public StateResponse delete() {
log.info("delete");
client.deleteState(STATE_STORE_NAME, STATE_STORE_KEY).block();
StateResponse response = new StateResponse();
response.setCode(1);
response.setStatus("delete");
return response;
}
}
复制代码
另外,在application.properties
中配置:
启动服务
在启动之前先用mvn
命令打包:
在state-management
项目的目录中执行以下命令,启动state-management
服务:
dapr run --app-id state-management --app-port 30003 --dapr-http-port 31003 -- java -jar target/state-management-0.0.1-SNAPSHOT.jar
复制代码
在 Dapr Dashboard 中看到:
服务都已经启动成功。
先访问http://localhost:30003/get,可以看到:
读取状态返回为 null,接下来访问http://localhost:30003/save?value=万猫学社,可以看到:
状态已经保存了,再访问http://localhost:30003/get验证一下:
状态被正确读取,再访问http://localhost:30003/delete,可以看到:
状态已经被删除了,再访问http://localhost:30003/get验证一下:
读取状态返回为 null。
状态储存组件
初始化 Dapr 后,默认为我们指定的状态储存组件是 Redis,在用户目录下的.dapr
文件夹中的components
文件夹中,可以找到statestore.yaml
文件:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.redis
version: v1
metadata:
- name: redisHost
value: localhost:6379
- name: redisPassword
value: ""
- name: actorStateStore
value: "true"
复制代码
下面让我们来尝试一下,使用 MySQL 作为状态储存组件,把statestore.yaml
文件修改为:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.mysql
version: v1
metadata:
- name: connectionString
value: "root:one.more.society@tcp(127.0.0.1:3306)/?allowNativePasswords=true"
复制代码
重新启动服务,可以看到在日志中看到使用 MySQL 作为状态储存组件:
time="09:57:35.5632633+08:00" level=info msg="Creating MySql schema 'dapr_state_store'" app_id=state-management instance=JT-243137 scope=dapr.contrib type=log ver=1.7.3
time="09:57:35.5862126+08:00" level=info msg="Creating MySql state table 'state'" app_id=state-management instance=JT-243137 scope=dapr.contrib type=log ver=1.7.3
time="09:57:35.6563599+08:00" level=info msg="component loaded. name: statestore, type: state.mysql/v1" app_id=state-management instance=JT-243137 scope=dapr.runtime type=log ver=1.7.3
复制代码
如果在 MySQL 中没有对应的库和表,Dapr 默认为我们自动创建一个名为dapr_state_store
的库,还有一个名为state
的表,如下图:
其中,state
的表结构为:
CREATE TABLE `state` (
`id` varchar(255) NOT NULL,
`value` json NOT NULL,
`isbinary` tinyint(1) NOT NULL,
`insertDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updateDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`eTag` varchar(36) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
复制代码
再访问一下http://localhost:30003/save?value=万猫学社,就可以在数据库中看到对应的数据:
值得注意的是:MySQL 状态储存组件目前还处于 Alpha 状态,最好不要在生产环境使用。
更详细的配置说明见下表:
配置示例:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.mysql
version: v1
metadata:
- name: connectionString
value: "root:one.more.society@tcp(127.0.0.1:3306)/?allowNativePasswords=true&tls=custom"
- name: schemaName
value: "one_more_state_store"
- name: tableName
value: "one_more_state"
- name: pemPath
value: "/one/more/society/file.pem"
复制代码
最后,感谢你这么帅,还给我点赞。
评论