开源界,本是技术爱好者百花齐放、各显其能的地方。但是,不管什么好东西,到了这块奇葩的土地都能变了味。现在的开源界,真的是鱼龙混杂,有些开源软件,不知道是噱头喊得高,还是star刷得好,竟能凭借一身垃圾代码招摇撞骗,误人子弟。垃圾不扫,这世界只能越来越臭。以iBase4J为例,我来给大家分析一下,让大家提高警惕,尤其是编程新手,不要上了贼船,免得抱撼终身。

1. iBase4J是什么东西

iBase4J,作者自称是一个JAVA(原文如此)分布式快速开发平台。项目的Github地址是https://github.com/iBase4J/iBase4J。截至本文的撰写时间(2018年7月3日,自由日前夕),该项目已有943个Star。在码云https://gitee.com/iBase4J/iBase4J上,该项目甚至有6422个Star,而且竟然是GVP(码云最有价值开源项目),这就是所谓鸡犬升天?

项目的官方介绍:

JAVA分布式快速开发平台:Spring,SpringBoot 2.0,SpringMVC,Mybatis,mybatis-plus,motan/dubbo分布式,Redis缓存,Shiro权限管理,Spring-Session单点登录,Quartz分布式集群调度,Restful服务,QQ/微信登录,App token登录,微信/支付宝支付;日期转换、数据类型转换、序列化、汉字转拼音、身份证号码验证、数字转人民币、发送短信、发送邮件、加密解密、图片处理、excel导入导出、FTP/SFTP/fastDFS上传下载、二维码、XML读写、高精度计算、系统配置工具类等等。SpringBoot版本:https://github.com/iBase4J/iBase4J-SpringBoot http://gitee.com/signup?inviter=iBase2J

2. 我与iBase4J的渊源

话说,我本不是什么路见不平,拔刀相助的侠客,而是鲁迅笔下的一个小小的看客。对于这种垃圾项目,敬而远之对我来说本是最佳选择。但是,自称iBase4J原作者的"万明"欠了我五千多的工资不发(如此如此,这般这般),就跟我结下了梁子。

iBase4J的作者叫“沈华杰”,河南人,万明(南充巴蜀文化传媒)的小弟。万明曾向我得意地说他才是iBase4J的原作者。我在这家公司负责前后端接口调试,后端是沈华杰用他的iBase4J写的。我被克扣工资愤而离职后,万明借口我什么都没做,交接工作没做好(我写了1万字以上的交接文档,能讲的都讲了,万明说新同事看了我的文档完全看不懂,接手不了,我调试过的接口全部都重写了(服,接口不都是你家沈华杰写的?我只是来调试和维护的)),不发工资,而且是一毛不发。

狼狈为奸者,一路货色也。当初维护iBase4J写的项目,搞得我焦头烂额。现在正好记录一下,让大家共赏。

3. 从项目主页看起

首先,JAVA 四个字母用的是全大写。众所周知,Java 名字的由来是印尼的爪哇岛,是地名,不是词组的简写。作为一个合格的 Java 程序员,对于给了咱饭碗的 Java 语言,至少要尊重人家的名字吧。全大写的 JAVA,由一个 Java 程序员拼写出来,完全是不伦不类。

然后,看 README 中的这句话

持久层:mybatis持久化,使用MyBatis-Plus优化,减少sql开发量;aop切换数据库实现读写分离。Transtraction注解事务。

文法内容先略过不表。单说Transtraction,英文中完全没有这个词汇。事务,作为数据库的核心概念之一,相信程序员们对于这个词都熟悉得很。我当然也不例外,当初打开这个项目主页,一眼就瞅到这个不三不四的单词,二话没说Fork下来改正拼写,然后提交Pull request。我好心好意帮你修正这低级错误,为了不伤你自尊,提交信息我还是用的纯英文的Update readme.md。结果,到现在都没改过来。没有任何反馈,就在二十多天后悄悄把这个Pull request给关了。

首页的其他地方也有槽点,不过我不是来找碴的,先架起项目再说。

4. 搭建环境与运行项目

iBase4J有SpringBoot版,是在另一个git仓库(https://github.com/iBase4J/iBase4J-SpringBoot)。既然有SpringBoot版,就优先使用SpringBoot版吧。

先查查文档怎么介绍的。结果只能在 README 里头找到这两句有点用的:

启动方法:
SysServiceApplication.java
SysWebApplication.java

具体的文档还需要加QQ群才能下载:

加入QQ群538240548
交流技术问题,下载项目文档和一键启动依赖服务工具。

既然没有文档,就直接导入IDE执行吧。

先把项目源码克隆到本地,再用 Jetbrains IDEA 打开。IDEA 会在后台自动下载 Maven 依赖。

依赖下载完成后,先启动 SysServiceApplication.java ,控制台一屏的报错。

先不说这报错,先看看日志的打印。SpringBoot默认情况下,打印的是彩色的日志,报错信息红色显示,十分醒目。但这个 ibase4J 放着 SpringBoot 精心设计好的日志格式不用,非要在 resources 目录创建一个 log4j2.xml ,打印了满屏的黑色。还有一堆乱码日志 [main] DEBUG [DefaultVFS:102] - Reader entry: ����4? 不知道是怎么搞出来的。

接下来看具体的报错。

报的第一个错是

main ERROR Unable to create file /output/logs/iBase4J-SYS-Service-dev/iBase4J-SYS-Service.log java.io.IOException: Could not create directory /output/logs/iBase4J-SYS-Service-devat org.apache.logging.log4j.core.util.FileUtils.mkdir(FileUtils.java:127)at org.apache.logging.log4j.core.util.FileUtils.makeParentDirs(FileUtils.java:144)at org.apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory.createManager(RollingFileManager.java:627)

显然,是 log4j 创建日志文件失败,日志的根目录竟然是 /output。你日志文件默认不写到工作目录,非要在系统根目录创建一个文件夹 output ?在类UNIX系统上,普通用户必然没有权限在系统根目录创建文件夹。好吧,那就先把这个日志文件夹创出来。执行命令 sudo mkdir /output && sudo chmod 777 /output,创建文件夹 /output 并把权限开到最大,不然普通用户也没有这个 /output 目录的写权限。

目录建好后,再次运行,第二个报错是:

[main] ERROR [DruidDataSource:870] - init datasource error, url: jdbc:mysql://127.0.0.1:3306/ibase4j?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&allowMultiQueries=true&serverTimezone=PRC&useSSL=false
java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:127) ~[mysql-connector-java-8.0.11.jar:8.0.11]`

数据库连接失败,访问被拒绝。无可厚非,毕竟我还没配数据库呢。理论上,数据库应该配在 Spring Boot 的标准配置文件 application.yml 里头。但是里头没有。找着一个 resources/config/dev/jdbc.properties ,看名字数据库应该就在这里配置了。

在这里配置也算不错了,ibase4J 之前的数据库可是配置在 pom.xml 中的。2018年5月18日,我离职6天后,沈华杰锅没地方甩了,估计也被自己这奇葩的配置方式绕晕了,老老实实把数据库配置放到了 properties 文件里。

数据库连接的默认配置如下:

druid.reader.url=jdbc:mysql://127.0.0.1:3306/ibase4j\u003fuseUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&allowMultiQueries=true&serverTimezone=PRC&useSSL=false
druid.reader.username=root
druid.reader.password=68NKG7n1mN8rErEfbag2qM==
druid.writer.url=jdbc:mysql://127.0.0.1:3306/ibase4j\u003fuseUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&allowMultiQueries=true&serverTimezone=PRC&useSSL=false
druid.writer.username=root
druid.writer.password=68NKG7n1mN8rErEfbag2qM==

竟然把半角问号(?)用 UNICODE 码(\u003f)表示,这个逼装的,我给打99分,不打100分是怕你骄傲。

数据库配置好后,再启动应用。这下报的错是:

[main] ERROR [SpringApplication:842] - Application run failed
java.lang.RuntimeException: 解密错误,错误信息:at top.ibase4j.core.util.SecurityUtil.decryptDes(SecurityUtil.java:134) ~[ibase4j-common-3.4.4.jar:?]at top.ibase4j.core.config.Configs.postProcessEnvironment(Configs.java:53) ~[ibase4j-common-3.4.4.jar:?]at org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEnvironmentPreparedEvent(ConfigFileApplicationListener.java:183) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]

好吧,数据库密码竟然要加密处理。找到解密逻辑,代码如下:

if ("druid.password,druid.writer.password,druid.reader.password".contains(keyStr)) {String dkey = (String)map.get("druid.key");dkey = DataUtil.isEmpty(dkey) ? Constants.DB_KEY : dkey;value = SecurityUtil.decryptDes(value.toString(), dkey.getBytes());map.put(key, value);
}

由于默认情况下 druid.key 是空值,加密的密钥取了默认值 90139119 ,这又是什么鬼?

调用top.ibase4j.core.util.SecurityUtil#encryptDes(java.lang.String, byte[])算出加密后的本机数据库密码后,更新数据库配置,再次启动应用。这次报的错是

[main] ERROR [JobStoreSupport$ClusterManager:3926] - ClusterManager: Error managing cluster: Failure obtaining db row lock: Table 'foo.qrtz_locks' doesn't exist
org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: Table 'foo.qrtz_locks' doesn't existat org.quartz.impl.jdbcjobstore.StdRowLockSemaphore.executeSQL(StdRowLockSemaphore.java:157) ~[quartz-2.3.0.jar:?]at org.quartz.impl.jdbcjobstore.DBSemaphore.obtainLock(DBSemaphore.java:113) ~[quartz-2.3.0.jar:?]

显然,缺少 Quartz 相关的数据表。导入sqls/3.quartz.mysql.sql后,再次启动应用。这次报错是:

2018-07-04 11:03:30.287 [main] DEBUG [RetryLoop:171] - Retry-able exception received
org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /dubbo/org.ibase4j.service.SchedulerService/providersat org.apache.zookeeper.KeeperException.create(KeeperException.java:102) ~[zookeeper-3.4.12.jar:3.4.12--1]

显然,Zookeeper没启动。启动Zookeeper,在启动应用,接下来的报错是:

[main] ERROR [SpringApplication:842] - Application run failed
org.springframework.jdbc.BadSqlGrammarException:
### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Table 'foo.sys_user' doesn't exist

显然,缺用户表。导入 sqls/1.iBase4J.sql,报错ERROR 1044 (42000) at line 16: Access denied for user 'foo'@'%' to database 'ibase4j'。iBase4J 竟然把数据库名写死在 SQL 里。

去掉数据库选择的 SQL , 再次导入,这次报错 ERROR 1273 (HY000) at line 232: Unknown collation: 'utf8' 。不懂,应该是我机器上没有叫utf8的字符集吧,可能新版本MySQL把这个字符集改名了。

去掉字符集设置,这次终于导入成功。启动应用,这次终于算是启动完成吧:

[main] INFO [ApplicationReadyListener:35] - =================================
[main] INFO [ApplicationReadyListener:38] - 系统[SysServiceApplication]启动完成!!!
[main] INFO [ApplicationReadyListener:39] - =================================

由于这个应用 "SysServiceApplication" 启动的是 Java RPC 服务,因此得启动一个 RPC 的客户端才能验证能否正常工作。

启动 org.ibase4j.SysWebApplication,一次启动完成。这个应用提供的是系统管理的 HTTP 接口。接下来测试一下。

访问 http://localhost:8088,返回一个302,跳转到 /index.html ,这个 /index.html 又302跳转到 /unauthorized,返回如下的 JSON:

{"code": "401","msg": "您还没有登录","timestamp": "1530675700497"
}

一个接口的首页,竟然用跳转,还跳了两次,也是没谁了。。。

访问 http://localhost:8088/swagger-ui.html,Swagger能进去。那就先看看这个接口的设计吧。

HTTP方法 URI Swagger描述 我的备注
PUT /user/read/list 查询用户 查询所有用户
PUT /user/read/detail 用户详细信息 查询单个用户
POST /user 修改用户信息 新增及更新用户
DELETE /user 删除用户 删除用户

显然,这接口的设计跟 REST 规范相去甚远,但是用 "PUT" 来进行查询操作也太匪夷所思了吧。新增与修改共用一个接口,这 iBase4J 不仅开源还会节流呢

找到登录接口 POST /login,空参先调用一下,接口报错:

{"code": "500","msg": "系统走神了,请稍候再试.","timestamp": "1530698198011"
}

所有的系统错误,全部返回“系统走神了,请稍候再试.”。。。

控制台报错:

[http-nio-8088-exec-19] ERROR [WebUtil:142] - java.lang.IllegalStateException: getInputStream() has already been called for this requestat org.apache.catalina.connector.Request.getReader(Request.java:1232)at org.apache.catalina.connector.RequestFacade.getReader(RequestFacade.java:504)at javax.servlet.ServletRequestWrapper.getReader(ServletRequestWrapper.java:225)at top.ibase4j.core.util.WebUtil.getRequestBody(WebUtil.java:135)at top.ibase4j.core.util.WebUtil.getParameter(WebUtil.java:164)at top.ibase4j.core.interceptor.EventInterceptor.afterCompletion(EventInterceptor.java:82)

意思是输入流已经打开过了,不能再次打开。做Java竟然不知道流只能打开一回。。。

这个bug之所以顽固到现在,是因为只要请求体不为空,就不复现。

登录的具体逻辑在 org.ibase4j.core.shiro.AuthorizeRealm 中,代码如下:

// 登录验证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)throws AuthenticationException {UsernamePasswordToken token = (UsernamePasswordToken)authcToken;Map<String, Object> params = new HashMap<String, Object>();params.put("enable", 1);params.put("account", token.getUsername());List<?> list = sysUserService.queryList(params);if (list.size() == 1) {SysUser user = (SysUser)list.get(0);StringBuilder sb = new StringBuilder(100);for (int i = 0; i < token.getPassword().length; i++) {sb.append(token.getPassword()[i]);}if (user.getPassword().equals(SecurityUtil.encryptPassword(sb.toString()))) {ShiroUtil.saveCurrentUser(user.getId());saveSession(user.getAccount(), token.getHost());AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getAccount(), sb.toString(),user.getUserName());return authcInfo;}logger.warn("USER [{}] PASSWORD IS WRONG: {}", token.getUsername(), sb.toString());return null;} else {logger.warn("No user: {}", token.getUsername());return null;}
}

其中 sysUserService 是一个 RPC 服务。现在这种调用比以前可强太多了,以前我在职的时候,全部RPC调用都走的是同一个接口,
代码如下:

// 权限
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();Long userId = (Long)ShiroUtil.getCurrentUser();Parameter parameter = new Parameter("sysAuthorizeService", "queryPermissionByUserId", userId);logger.info("{} execute queryPermissionByUserId start...", parameter.getNo());List<?> list = sysProvider.execute(parameter).getResultList();logger.info("{} execute queryPermissionByUserId end.", parameter.getNo());for (Object permission : list) {if (StringUtils.isNotBlank((String)permission)) {// 添加基于Permission的权限信息info.addStringPermission((String)permission);}}// 添加用户权限info.addStringPermission("user");return info;
}

看这一行Parameter parameter = new Parameter("sysAuthorizeService", "queryPermissionByUserId", userId);,调用的服务、
调用的方法全部通过字符串来传递,返回的结果再从Object向下强转。广义上说,应该算是自定义了一套协议了吧。
通过字符串调用服务,PHP和Ruby都不这么干吧?牛!

具体的调用逻辑:

@Override
public Parameter execute(Parameter parameter) {String no = parameter.getNo();logger.info("{} request:{}", no, JSON.toJSONString(parameter));Object service = applicationContext.getBean(parameter.getService());try {String method = parameter.getMethod();Object[] param = parameter.getParam();Object result = InstanceUtil.invokeMethod(service, method, param);Parameter response = new Parameter(result);logger.info("{} response:{}", no, JSON.toJSONString(response));return response;} catch (Exception e) {logger.error(no + " " + Constants.Exception_Head, e);throw e;}
}

这个方法参数用Parameter,返回类型还用Parameter,这就是传说中的惜码如金吧?

rpc调用通过top.ibase4j.core.base.provider.IBaseProvider#execute(top.ibase4j.core.base.provider.Parameter)方法,方法的参数和返回值均是一个Parameter对象。做参数时,调用构造函数Parameter(beanName, methodName, argList)。做返回结果时,getResult取对象,getResultList取列表,getResultPage取分页,getResultLong取整数

具体的查询数据库代码如下

@Override /** 根据参数查询 */
public List<T> queryList(Map<String, Object> params) {if (DataUtil.isEmpty(params.get("orderBy"))) {params.put("orderBy", "id_");}if (DataUtil.isEmpty(params.get("sortAsc"))) {params.put("sortAsc", "desc");}List<Long> ids = mapper.selectIdPage(params);List<T> list = queryList(ids);return list;
}

作为一套框架,字符串不传参数,不传枚举,不传常量,也不写文档,硬生生地就写在 Map 里。
至于sortAscselectIdPage之类的命名风格,还需要细细品味。

由于时间有限,我就不慢慢深入了。在此再列出几条突出的槽点,供大家品鉴:

1. 项目的配置文件到处都是

修改配置的时候,寻找配置项所在的位置极其痛苦。甚至部分配置扔在jar包里,部署后想要修改这些配置,还得解包jar,再重新打包。自定义的配置是通过org.springframework.core.io.support.PathMatchingResourcePatternResolver#getResources("classpath\*:config/\*.properties")方法获取。此方法依次从当前项目、依赖模块、依赖jar的config目录读取properties文件,不搞懂优先规则,配置好的东西就被莫名其妙地覆盖掉了。

2. 数据库查询的queryById的代码匪夷所思

private T queryById(Long id, int times) {CacheKey key = CacheKey.getInstance(getClass());T record = null;if (key != null) {try {record = (T)CacheUtil.getCache().get(key.getValue() + ":" + id, key.getTimeToLive());} catch (Exception e) {logger.error(Constants.Exception_Head, e);}}if (record == null) {String lockKey = getLockKey(id);String requestId = Sequence.next().toString();if (CacheUtil.getLock(lockKey, "根据ID查询数据", requestId)) {try {record = mapper.selectById(id);saveCache(record);} finally {CacheUtil.unLock(lockKey, requestId);}} else {if (times > 3) {record = mapper.selectById(id);saveCache(record);} else {logger.debug(getClass().getSimpleName() + ":" + id + " retry getById.");sleep(100);return queryById(id, times + 1);}}}return record;
}

递归调用、睡眠100毫秒、计次。。。

queryById 先读缓存,如果缓存有效,直接返回。
否则,获取锁(60秒超时)并调用com.baomidou.mybatisplus.mapper.BaseMapper#selectById。
没获取到锁,则继续获取两次,如果还没获取到锁,则直接#selectById。
查询到的数据继续加入缓存。

最基本的用ID查询数据,你们能看懂吗?

3. 用户的Token由客户端生成

用户的Token不在服务端生成,反而要客户端生成,还没有格式限制,你不嫌头大?

4. 一个用户一个密钥

正常情况下,只要私钥保存在服务器,一对密钥就足够安全了。可是这iBase4J的密钥要客户端调接口去申请,
服务端生成密钥对保存在Redis里。一个用户一个密钥,哥们,你真有苦!

5. 签名算法把FBI都弄哭了

iBase4J的签名算法是:请求参数按key顺序排序,组成URL查询串,取前100各字符,MD5哈希成Base64格式,后缀一个"\r\n",最后用私钥签名。
哥们,你这九曲回肠的签名方法,把FBI都弄哭了!

6. Git日志几乎清一色的“优化”

以下是截取的最近的几条Git提交日志(git log --oneline | cat

e110a6da 优化
654db900 优化
1daba720 优化
20834312 优化缓存管理
f595b17f 优化
f4d9683d 修改bug
73593c9b 优化
ab0d465e 优化读取request.body
fb5f300c 优化
5e3d5e4d SQL
bf8a44d9 庆祝国人加入JCP
ad3b0047 庆祝国人加入JCP
603fb11f 庆祝国人加入JCP
ae7e968f 优化-庆祝国人加入JCP
c44d888c 优化
5228bce1 优化
4cd3257d 优化
7973d0b9 优化配置
6fb59931 优化配置
6393156c 优化配置
17de6d23 优化FDFS
c6bb4e70 优化
b5ea3662 JSTL
c619c366 省-市-区县
443a6b60 优化邮件模块
101c0f0c 优化发送邮件
0c87fd5c 优化
929d7a07 发送邮件
93c66a68 优化配置

不知道这位“Git优化大师”是在解释什么,还是在掩饰什么。。。

这iBase4J的槽点太多,我实在吐不过来了,JavaScript代码还没提到。软件写成这样,自己用就得了,还出来招摇撞骗、误人子弟就太过分了。

捐赠要钱、文档要钱、加群交流要钱、后台UI也要钱,能要钱的地方你一个都拉不下,哥们你想钱想疯了,还有心思写代码吗???

希望大家多多转载,多多评价,还开源界一片净土!

文章首发:https://baijifeilong.github.io/2018/07/03/ibase4j

转载于:https://www.cnblogs.com/baijifeilong/p/9266514.html

警惕挂着开源的招牌到处坑蒙拐骗的垃圾项目,比如iBase4J相关推荐

  1. 开源软件学习交流计划 (西游记项目)

    试试搞一个项目,推广开源软件的学习和交流,项目名称:开源软件学习交流计划.再弄个好玩好记的项目名字:西游记. 西游记嘛,有一个好玩的过程,主要是把西方的开源软件学习过来(当然更支持我们自己的项目,比如 ...

  2. sm4 前后端 加密_这7个开源的Spring Boot前后端分离项目整理给你

    来源|公众号:江南一点雨 前后端分离已经开始逐渐走进各公司的技术栈,不少公司都已经切换到前后端分离开发技术栈上面了,因此建议技术人学习前后端分离开发以提升自身优势.同时,也整理了 7 个开源的 Spr ...

  3. 开源前端脚本错误监控及跟踪解决项目BadJS试用

    摘要: 试用BadJS. 原文:开源前端脚本错误监控及跟踪解决项目-BadJS 试用 作者:过错 Fundebug经授权转载,版权归原作者所有. BadJS 是 一个web 前端脚本错误监控及跟踪项目 ...

  4. 开源之夏 2022 开启,提交项目当导师

    活动简介 "开源之夏(英文简称 OSPP)"是中科院软件所"开源软件供应链点亮计划"指导下的系列暑期活动,由软件所与 openEuler 社区共同主办. 开源之 ...

  5. java民宿开源_在线民宿满意度测评项目[开源]

    原标题:在线民宿满意度测评项目[开源] 重庆市在线民宿满意度测评项目,负责数据采集.主题抽取.情感分析等任务.开发的目的是克服用户打分和评论不一致,实时对重庆地区在线民宿的满意度进行评测,使用Pyth ...

  6. 滴滴开源在2019:十大重点项目盘点,DoKit客户端研发助手首破1万Star

    整理 | Jane 出品 | AI科技大本营(ID:rgznai100) 2018 年,科技企业纷纷布局开源战略后迎来的第一个"丰收年".但对滴滴来说,2019 年才迎来其第一波开 ...

  7. 前后端分离项目_七个开源的 Spring Boot 前后端分离项目,一定要收藏

    来自公众号:江南一点雨 前后端分离已经在慢慢走进各公司的技术栈,根据松哥了解到的消息,不少公司都已经切换到这个技术栈上面了.即使贵司目前没有切换到这个技术栈上面,松哥也非常建议大家学习一下前后端分离开 ...

  8. 阿里云开源业内首个应用多活项目 AppActive,与社区共建云原生容灾标准

    作者:中西(github @zhongxig),AppActive 负责人,来自阿里云云原生高可用架构团队,从事容灾架构和故障快恢的研发和开源工作. 摘要: 继高可用架构团队的 Sentinel.Ch ...

  9. 开源中国众包第二波阿里云悬赏项目,总金额30万

    昨天开源中国众包平台正式发布了合作伙伴 -- 阿里云的第一波的3个悬赏项目,总金额10万(详情),目前三个项目已经结束报名正式进入开发阶段. 现在第二波4个悬赏项目已经发布,总金额超过30万,分别是: ...

最新文章

  1. 蓝桥杯java第五届决赛第一题--国王的遗产
  2. 【转载】OpenStack Swift学习笔记
  3. MonoBehaviour常用方法
  4. Mybatis-Plus 使用自定义注入器后,查询条件中不再添加逻辑删除字段限定条件
  5. iphone换机数据迁移_iPhone 与安卓手机备份与资料迁移的方法
  6. Python创建cvs文件,包含标签和图片数据
  7. ospf避免环路_13、OSPF的选路规则及路由控制
  8. c语言网吧添加卡,c语言网吧计费系统源代码.docx
  9. Centos7 Kubernetes(k8s) 开发服务器(单服务器)部署 zipkin 链路跟踪
  10. 疫情防控背景下在线课程教学满意度影响因素分析与对策探讨-以电子商务及法律专业为例
  11. 读入外挂:ios::sync_with_stdio(false)
  12. 在第四代计算机期间全世界逐步进入了,1、在第四代计算机期间内,计算机的应用逐步进入到.docx.docx...
  13. 罗马帝国开创了辉煌的人类文明,但他们的数字表示法的确有些繁琐,尤其在表示大数的时候,现在看起来简直不能忍受,所以在现代很少使用了。之所以这样,不是因为发明表示法的人的智力的问题,而是因为一个宗教的原因
  14. 计算机科学 vs 计算机技术
  15. 游戏公司如何应对游戏黑产 ?
  16. Loki告警的正确姿势
  17. 使用python的zipfile模块巧解word批量生成问题
  18. 软工小队第二次会议 4-23
  19. 英国第一毒舌天才王尔德的损人金句
  20. oracle数据库添加外键约束

热门文章

  1. 解决ubuntu下提示未信任的应用启动器的问题
  2. TCN 一维预测の笔记
  3. 通用管理后台系统 spring-boot-plus2 (自研)
  4. java基于ssm的教材征订信息管理系统
  5. arcgis runtime100(九、十课时)
  6. 文都网校考研英语全套资料
  7. Halcon 《机器视觉算法及应用》十例(其二)
  8. 并联四足机器人项目开源教程(五) --- 四足机器人相关书籍论文研读
  9. javascript ←AES.CBC→ go 相互加密解密
  10. 检查 Docker 版本,重装 Docker