三方标准中间件对接
概念说明
应用开始对接前,需要先梳理整个应用系统,将应用分成一个或者多个“自研节点”和标准中间件。顾名思义,“自研节点”是指ISV自行开发的应用模块,通常是一个开发工程产出的执行体。本产品文档所提及的“中间件”,是指可独立运行的系统组件,如MySQL、Redis、MongoDB数据库等。区别于系统所使用的技术框架,又与之有关。比如使用Dubbo作为开发框架,Dubbo本身不是本文所说的“中间件”,但是与Dubbo搭配使用的ZooKeeper,就是这里所谓的“中间件”。目前,平台提供的中间件相关的节点分成两类:
三方节点:这些中间件来自于标准的开源中间件镜像,平台本身并不修改或者保证该中间件本身的能力。
初始化节点:这些节点只运行一次,他们并不是真正意义上的中间件,而仅仅完成中间件的一些初始化业务,平台层面会保证这些节点在应用部署运行的整个生命周期只会被成功执行一次。
部署与访问
对中间件节点的访问,一般情况下,直接使用该节点对“服务名称”作为地址即可;对中间件的部署,是平台支持情况,分成两种:
平台已支持
直接在可视化编排界面进行拖拽和配置即可,左侧即为支持的节点,中间部分为画布,右侧部分为节点属性,如下图所示: 
平台未支持
平台支持对中间件尚在不停的完善中,如果发现有不支持的中间件,可以联系相应的商务渠道进行沟通。当然,如果满足如下条件,ISV可以自行将中间件达成镜像包,作为自研节点供系统使用:
应用中,对该中间件的使用,并不涉及到持久化,或者数据允许丢失,或者可以指定明确的持久化路径。
应用中,对该中间件的使用,仅需要单节点使用,不使用集群或者高可用能力。
中间件通讯方式
操作系统  | 中间件类型  | 中间件名称  | 访问节点方式  | 
Linux  | 阿里云中间件  | IotEdge  | 固定的服务名称 iotedge  | 
LinkVisual  | 固定的服务名称 linkvisual  | ||
三方中间件  | RedisHA  | 使用服务名称  | |
SQL Server  | 使用服务名称  | ||
Redis  | 使用服务名称  | ||
MySQL-HA  | 使用服务名称  | ||
RubbitMQ  | 使用服务名称  | ||
Prometheus  | 使用服务名称  | ||
Grafana  | 使用服务名称  | ||
MySQL  | 使用服务名称  | ||
InfluxDB  | 使用服务名称  | 
中间件环境变量说明
节点分类  | 环境变量字段  | 环境变量key  | 环境变量value  | 
自研节点  | 应用appkey  | iot.hosting.appKey  | |
应用appsecret  | iot.hosting.appSecret  | ||
IoT官方API调用域名  | iot.hosting.api.domain  | ||
IoT官方API调用协议  | iot.hosting.api.schema  | HTTP/HTTPS  | |
IoT服务模型API调用域名  | iot.hosting.mesh.domain  | ||
IoT服务模型API调用协议  | iot.hosting.mesh.schema  | HTTP/HTTPS  | |
redis-ha  | 服务地址  | iot.hosting.${name}.redisUrl  | |
登录密码  | iot.hosting.${name}.redisPassword  | ||
sqlserver  | 数据库用户名  | iot.hosting.${name}.mssqlUser  | |
数据库密码  | iot.hosting.${name}.mssqlPassword  | ||
数据库database  | iot.hosting.${name}.mssqlDatabase  | ||
redis  | 服务地址  | iot.hosting.${name}.redisUrl  | |
登录密码  | iot.hosting.${name}.redisPassword  | ||
mysql-ha  | 服务地址  | iot.hosting.${name}.mysqlHost  | |
数据库database  | iot.hosting.${name}.mysqlDatabase  | ||
数据库密码  | iot.hosting.${name}.mysqlPassword  | ||
数据库用户  | iot.hosting.${name}.mysqlUser  | ||
数据库url  | iot.hosting.${name}.mysqlUrl  | jdbc:mysql://${name}:3306/${mysqlDatabase}  | |
rabbitmq  | 服务地址  | iot.hosting.${name}.rabbitmqHost  | |
登录账户  | iot.hosting.${name}.rabbitmqUsername  | ||
登录密码  | iot.hosting.${name}.rabbitmqPassword  | ||
mysql  | 数据库用户名  | iot.hosting.${name}.mysqlUser  | |
数据库密码  | iot.hosting.${name}.mysqlPassword  | ||
数据库database  | iot.hosting.${name}.mysqlDatabase  | ||
数据库地址  | iot.hosting.${name}.mysqlUrl  | jdbc:mysql://${name}:3306/${mysqlDatabase}  | |
influxdb  | 服务地址  | iot.hosting.${name}.influxdbHost  | http://${name}:8086  | 
数据库database  | iot.hosting.${name}.influxdbDatabase  | ||
数据库用户  | iot.hosting.${name}.influxdbUser  | ||
数据库密码  | iot.hosting.${name}.influxdbPassword  | 
参数说明:iot.hosting.${name}:指在应用配置中相应中间件的服务名称。
多副本应用部署
多副本部署目前仅支持RedisHA和MysqlHA的三方节点进行数据存储,在应用配置可选择副本数。如图所示:
MysqlHA实现步骤
安装MySQL应用
在两个副本中创建slave同步账户,并授予对应的权限
grant replication slave on *.* to 'slave'@'%' identified by 'Abcd@1234';
flush privileges;配置数据库选项,参考配置如下:
实例1:
server-id=1
log-bin=mysql-bin
relay-log=mysql-relay-bin
log-slave-updates=on
auto-increment-increment=2
auto-increment-offset=1实例2:
server-id=2
log-bin=mysql-bin
relay-log=mysql-relay-bin
log-slave-updates=on
auto-increment-increment=2
auto-increment-offset=2启动slave进程;
#实例1
CHANGE MASTER TO MASTER_HOST='192.168.99.118',MASTER_USER='slave',MASTER_PASSWORD='Abcd@1234';
#实例2
CHANGE MASTER TO MASTER_HOST='192.168.99.117',MASTER_USER='slave',MASTER_PASSWORD='Abcd@1234';使用方式
初始化节点
与MySQL相同
JDBC连接
假设设置的mysql-ha服务名称为 mysqlha端口为3306
JDBC URL
jdbc:mysql://mysqlha-0.mysqlha:3306,mysqlha-1.mysqlha:3306/mysqlha?characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=false注意:
需要填入两个地址,分别为主地址
-0., 从地址-1.
设置属性
autoReconnect=true&failOverReadOnly=false
JDBC连接池
建议使用JDBC连接池,示例代码
public class DataSourceConfig {
    @Value("${datasource.url}")
    private String url;
    @Value("${datasource.username}")
    private String username;
    @Value("${datasource.password}")
    private String password;
    @Value("${datasource.max.active}")
    private int maxActive;
    @Value("${datasource.initial.size}")
    private int initialSize;
    @Bean(name = "dataSource")
    public DruidDataSource dataSource() {
        DruidDataSource novaDruidDataSource = new DruidDataSource();
        novaDruidDataSource.setUrl(url);
        novaDruidDataSource.setUsername(username);
        novaDruidDataSource.setPassword(password);
        novaDruidDataSource.setMaxActive(maxActive);
        novaDruidDataSource.setInitialSize(initialSize);
        novaDruidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        novaDruidDataSource.setValidationQuery("SELECT 1");
        novaDruidDataSource.setTestWhileIdle(true);
        novaDruidDataSource.setTimeBetweenEvictionRunsMillis(60000);
        return novaDruidDataSource;
    }
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        WrapAndChangeConfigureSqlSessionFactory factory = new WrapAndChangeConfigureSqlSessionFactory();
        factory.setDataSource(dataSource());
        factory.setTypeHandlers(intEnumTypeHandlersFactory().getObject().toArray(new TypeHandler<?>[0]));
        return factory.getObject();
    }
    @Bean(name = "typeHandlerList")
    public IntEnumTypeHandlersFactoryBean intEnumTypeHandlersFactory() {
        IntEnumTypeHandlersFactoryBean typeHandlersFactoryBean = new IntEnumTypeHandlersFactoryBean();
        typeHandlersFactoryBean.setBasePackage("com.aliyun.iotx.bean");
        return typeHandlersFactoryBean;
    }
    @Bean(name = "dataSourceTransactionManager")
    public DataSourceTransactionManager dataSourceTransactionManager() {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource());
        return dataSourceTransactionManager;
    }
    @Bean(name = "jdbcTemplate")
    public JdbcTemplate jdbcTemplate() {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource());
        return jdbcTemplate;
    }
}实例demo
下载地址: