技术

技术

详谈HTTPS SSL/TLS协议原理

科技创新森马 发表了文章 • 0 个评论 • 39 次浏览 • 2021-04-28 16:53 • 来自相关话题

协议安全和加密越来越引起人们的重视和关注,今天就跟大家分享一点协议加密方面的知识。要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识。大致了解几个基本术语(HTTPS、SSL、TLS)的含义大致了解 HTTP 和 TCP 的关系(尤其是 “短连接”... ...查看全部

协议安全和加密越来越引起人们的重视和关注,今天就跟大家分享一点协议加密方面的知识。要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识。

  1. 大致了解几个基本术语(HTTPS、SSL、TLS)的含义

  2. 大致了解 HTTP 和 TCP 的关系(尤其是 “短连接”VS“长连接”)

  3. 大致了解加密算法的概念(尤其是 “对称加密与非对称加密” 的区别)

  4. 大致了解 CA 证书的用途考虑到很多技术菜鸟可能不了解上述背景,俺先用最简短的文字描述一下。如果你自认为不是菜鸟,请略过本章节,直接去看 “HTTPS 协议的需求”。

一、先澄清几个术语——HTTPS、SSL、TLS。

1. “HTTP” 是干嘛用滴?

首先,HTTP 是一个网络协议,是专门用来帮你传输 Web 内容滴。关于这个协议,就算你不了解,至少也听说过吧?比如你访问俺的博客的主页,浏览器地址栏会出现如下的网址http://www.xxx.com/

俺加了粗体的部分就是指 HTTP 协议。大部分网站都是通过 HTTP 协议来传输 Web 页面、以及 Web 页面上包含的各种东东(图片、CSS 样式、JS 脚本)。

2. “SSL/TLS” 是干嘛用滴?

SSL 是洋文 “Secure Sockets Layer” 的缩写,中文叫做 “安全套接层”。它是在上世纪 90 年代中期,由网景公司设计的。(顺便插一句,网景公司不光发明了 SSL,还发明了很多 Web 的基础设施——比如“CSS 样式表” 和“JS 脚本”) 为啥要发明 SSL 这个协议捏?因为原先互联网上使用的 HTTP 协议是明文的,存在很多缺点——比如传输内容会被偷窥(嗅探)和篡改。发明 SSL 协议,就是为了解决这些问题。

到了 1999 年,SSL 因为应用广泛,已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为 TLS(是 “Transport Layer Security” 的缩写),中文叫做“传输层安全协议”。

很多相关的文章都把这两者并列称呼(SSL/TLS),因为这两者可以视作同一个东西的不同阶段。

3. “HTTPS” 是啥意思?

解释完 HTTP 和 SSL/TLS,现在就可以来解释 HTTPS 啦。咱们通常所说的 HTTPS 协议,说白了就是 “HTTP 协议” 和“SSL/TLS 协议”的组合。你可以把 HTTPS 大致理解为——“HTTP over SSL”或“HTTP over TLS”(反正 SSL 和 TLS 差不多)。

二、再来说说 HTTP 协议的特点

作为背景知识介绍,还需要再稍微谈一下 HTTP 协议本身的特点。HTTP 本身有很多特点,考虑到篇幅有限,俺只谈那些和 HTTPS 相关的特点。

1. HTTP 的版本和历史

如今咱们用的 HTTP 协议,版本号是 1.1(也就是 HTTP 1.1)。这个 1.1 版本是 1995 年底开始起草的(技术文档是 RFC2068),并在 1999 年正式发布(技术文档是 RFC2616)。

在 1.1 之前,还有曾经出现过两个版本 “0.9 和 1.0”,其中的 HTTP 0.9 没有被广泛使用,而 HTTP 1.0 被广泛使用过。另外,2015年IETF 就要发布 HTTP 2.0 的标准了。

2. HTTP 和 TCP 之间的关系

简单地说,TCP 协议是 HTTP 协议的基石——HTTP 协议需要依靠 TCP 协议来传输数据。在网络分层模型中,TCP 被称为 “传输层协议”,而 HTTP 被称为 “应用层协议”。

有很多常见的应用层协议是以 TCP 为基础的,比如 “FTP、SMTP、POP、IMAP” 等。

TCP 被称为 “面向连接” 的传输层协议。关于它的具体细节,俺就不展开了(否则篇幅又失控了)。你只需知道:传输层主要有两个协议,分别是 TCP 和 UDP。TCP 比 UDP 更可靠。你可以把 TCP 协议想象成某个水管,发送端这头进水,接收端那头就出水。并且 TCP 协议能够确保,先发送的数据先到达(与之相反,UDP 不保证这点)。

3. HTTP 协议如何使用 TCP 连接?

HTTP 对 TCP 连接的使用,分为两种方式:俗称 “短连接” 和“长连接”(“长连接”又称 “持久连接”,洋文叫做“Keep-Alive” 或“Persistent Connection”) 假设有一个网页,里面包含好多图片,还包含好多外部的CSS 文件和 JS 文件。在 “短连接” 的模式下,浏览器会先发起一个 TCP 连接,拿到该网页的 HTML 源代码(拿到 HTML 之后,这个 TCP 连接就关闭了)。然后,浏览器开始分析这个网页的源码,知道这个页面包含很多外部资源(图片、CSS、JS)。

然后针对每一个外部资源,再分别发起一个个 TCP 连接,把这些文件获取到本地(同样的,每抓取一个外部资源后,相应的 TCP 就断开) 相反,如果是 “长连接” 的方式,浏览器也会先发起一个 TCP 连接去抓取页面。但是抓取页面之后,该 TCP 连接并不会立即关闭,而是暂时先保持着(所谓的“Keep-Alive”)。然后浏览器分析 HTML 源码之后,发现有很多外部资源,就用刚才那个 TCP 连接去抓取此页面的外部资源。

在 HTTP 1.0 版本,默认使用的是 “短连接”(那时候是 Web 诞生初期,网页相对简单,“短连接” 的问题不大);到了 1995 年底开始制定 HTTP 1.1 草案的时候,网页已经开始变得复杂(网页内的图片、脚本越来越多了)。这时候再用短连接的方式,效率太低下了(因为建立 TCP 连接是有 “时间成本” 和“CPU 成本”滴)。

所以,在 HTTP 1.1 中,默认采用的是 “Keep-Alive” 的方式。关于 “Keep-Alive” 的更多介绍,可以参见维基百科词条。

三、谈谈 “对称加密” 和“非对称加密”的概念

1. 啥是 “加密” 和“解密”?

通俗而言,你可以把 “加密” 和“解密”理解为某种互逆的数学运算。就好比 “加法和减法” 互为逆运算、“乘法和除法”互为逆运算。

“加密”的过程,就是把 “明文” 变成 “密文” 的过程;反之,“解密”的过程,就是把 “密文” 变为“明文”。在这两个过程中,都需要一个关键的东东——叫做“密钥”——来参与数学运算。

2. 啥是 “对称加密”?

所谓的 “对称加密技术”,意思就是说:“加密” 和“解密”使用相同的密钥。这个比较好理解。就好比你用 7zip 或 WinRAR 创建一个带密码(口令)的加密压缩包。当你下次要把这个压缩文件解开的时候,你需要输入同样的密码。在这个例子中,密码 / 口令就如同刚才说的“密钥”。

3. 啥是 “非对称加密”?

所谓的 “非对称加密技术”,意思就是说:“加密” 和“解密”使用不同的密钥。这玩意儿比较难理解,也比较难想到。当年 “非对称加密” 的发明,还被誉为 “密码学” 历史上的一次革命。

由于篇幅有限,对 “非对称加密” 这个话题,俺就不展开了。有空的话,再单独写一篇扫盲。

4. 各自有啥优缺点?

看完刚才的定义,很显然:(从功能角度而言)“非对称加密”能干的事情比 “对称加密” 要多。这是 “非对称加密” 的优点。但是 “非对称加密” 的实现,通常需要涉及到 “复杂数学问题”。所以,“非对称加密” 的性能通常要差很多(相对于 “对称加密” 而言)。这两者的优缺点,也影响到了 SSL 协议的设计。

四、HTTPS 协议的需求是啥?

花了好多口水,终于把背景知识说完了。下面正式进入正题。先来说说当初设计 HTTPS 是为了满足哪些需求?

很多介绍 HTTPS 的文章一上来就给你讲实现细节。个人觉得:这是不好的做法。早在 2009 年开博的时候,发过一篇<学习技术的三部曲:WHAT、HOW、WHY>,其中谈到 “WHY 型问题” 的重要性。一上来就给你讲协议细节,你充其量只能知道 WHAT 和 HOW,无法理解 WHY。

俺在前一个章节讲了“背景知识”,在这个章节讲了“需求”,这就有助于你理解:当初为什么要设计成这样?——这就是 WHY 型的问题。

兼容性

因为是先有 HTTP 再有 HTTPS。所以,HTTPS 的设计者肯定要考虑到对原有 HTTP 的兼容性。这里所说的兼容性包括很多方面。比如已有的 Web 应用要尽可能无缝地迁移到 HTTPS;比如对浏览器厂商而言,改动要尽可能小;基于 “兼容性” 方面的考虑,很容易得出如下几个结论:

  1. HTTPS 还是要基于 TCP 来传输(如果改为 UDP 作传输层,无论是 Web 服务端还是浏览器客户端,都要大改,动静太大了)。

  2. 单独使用一个新的协议,把 HTTP 协议包裹起来 (所谓的 “HTTP over SSL”,实际上是在原有的 HTTP 数据外面加了一层 SSL 的封装。HTTP 协议原有的 GET、POST 之类的机制,基本上原封不动)。打个比方: 如果原来的 HTTP 是塑料水管,容易被戳破;那么如今新设计的 HTTPS 就像是在原有的塑料水管之外,再包一层金属水管。一来,原有的塑料水管照样运行;二来,用金属加固了之后,不容易被戳破。

可扩展性

前面说了,HTTPS 相当于是 “HTTP over SSL”。如果 SSL 这个协议在 “可扩展性” 方面的设计足够牛逼,那么它除了能跟 HTTP 搭配,还能够跟其它的应用层协议搭配。岂不美哉?

现在看来,当初设计 SSL 的人确实比较牛。如今的 SSL/TLS 可以跟很多常用的应用层协议(比如: FTP、SMTP、POP、Telnet)搭配,来强化这些应用层协议的安全性。

接着刚才打的比方: 如果把 SSL/TLS 视作一根用来加固的金属管,它不仅可以用来加固输水的管道,还可以用来加固输煤气的管道。

保密性

HTTPS 需要做到足够好的保密性。说到保密性,首先要能够对抗嗅探(行话叫 Sniffer)。所谓的 “嗅探”,通俗而言就是监视你的网络传输流量。如果你使用明文的 HTTP 上网,那么监视者通过嗅探,就知道你在访问哪些网站的哪些页面。

嗅探是最低级的攻击手法。除了嗅探,HTTPS 还需要能对抗其它一些稍微高级的攻击手法——比如 “重放攻击”。

完整性

除了 “保密性”,还有一个同样重要的目标是“确保完整性”。关于“完整性” 这个概念,在之前的博文<扫盲文件完整性校验——关于散列值和数字签名>中大致提过。健忘的同学再去温习一下。在发明 HTTPS 之前,由于 HTTP 是明文的,不但容易被嗅探,还容易被篡改。

举个例子: 比如咱们天朝的网络运营商都比较流氓,经常有网友抱怨说访问某网站(本来是没有广告的),竟然会跳出很多广告。为啥会这样捏?因为你的网络流量需要经过 ISP 的线路才能到达公网。如果你使用的是明文的 HTTP,ISP 很容易就可以在你访问的页面中植入广告。所以,当初设计 HTTPS 的时候,还有一个需求是 “确保 HTTP 协议的内容不被篡改”。

真实性

在谈到 HTTPS 的需求时,“真实性”经常被忽略。其实 “真实性” 的重要程度不亚于前面的 “保密性” 和“完整性”。

举个例子: 你因为使用网银,需要访问该网银的 Web 站点。那么,你如何确保你访问的网站确实是你想访问的网站?(这话有点绕口令) 有些天真的同学会说:通过看网址里面的域名来确保。

为啥说这样的同学是 “天真的”?因为 DNS 系统本身是不可靠的(尤其是在设计 SSL 的那个年代,连DNSSEC 都还没发明)。由于DNS 的不可靠(存在“域名欺骗” 和“域名劫持”),你看到的网址里面的域名未必是真实滴!所以,HTTPS 协议必须有某种机制来确保 “真实性” 的需求。

性能

再来说最后一个需求——性能。引入 HTTPS 之后,不能导致性能变得太差。否则的话,谁还愿意用?为了确保性能,SSL的设计者至少要考虑如下几点:

  1. 如何选择加密算法(“对称”or“非对称”)?

  2. 如何兼顾 HTTP 采用的 “短连接”TCP 方式?SSL 是在1995 年之前开始设计的,那时候的 HTTP 版本还是 1.0,默认使用的是 “短连接” 的 TCP 方式——默认不启用 Keep-Alive)。


日志审计系统的基本原理与部署方式

科技创新森马 发表了文章 • 0 个评论 • 34 次浏览 • 2021-04-28 11:43 • 来自相关话题

日志审计系统简介什么是日志审计?综合日志审计平台,通过集中采集信息系统中的系统安全事件、用户访问记录、系统运行日志、系统运行状态等各类信息,经过规范化、过滤、归并和告警分析等处理后,以统一格式的日志形式进行集中存储和管理,结合丰富的日志统计汇总及关联分析功能,... ...查看全部

日志审计系统简介

什么是日志审计?

综合日志审计平台,通过集中采集信息系统中的系统安全事件、用户访问记录、系统运行日志、系统运行状态等各类信息,经过规范化、过滤、归并和告警分析等处理后,以统一格式的日志形式进行集中存储和管理,结合丰富的日志统计汇总及关联分析功能,实现对信息系统日志的全面审计。

通过日志审计系统,企业管理员随时了解整个IT系统的运行情况,及时发现系统异常事件;另一方面,通过事后分析和丰富的报表系统,管理员可以方便高效地对信息系统进行有针对性的安全审计。遇到特殊安全事件和系统故障,日志审计系统可以帮助管理员进行故障快速定位,并提供客观依据进行追查和恢复。[百度百科]

为什么需要日志审计平台?

  1. 日志审计的合规要求,由于网络安全法的颁布实施,由原先的不合规转变成了不合法。如果不对要求的相关日志不做留存6个月以上,一旦追查,将面临法律责任。

  2. 安全运营的挑战。随着网络设备的增多,以及服务器数量的增多,如果没有统一的综合日志审计平台,那么需要登录到每台设备上查看日志,不利于运维人员管理。而且众多设备会产生海量的日志,无法有效管理。多种设备形成信息孤岛,日志无法关联分析。通过统一的日志审计平台,将所有设备日志都收集到日志平台进行统一管理,统一分析。

日志审计的核心目标:

  • 多源数据归一化

  • 日志存储集中化

  • 关联分析自动化

  • 安全态势立体化

日志审计的主要功能

设计思路:

统一日志采集:
  • 对不同日志源 (主机系统、网络设备、安全设备、应用中间件、数据库等)所产生的日志进行收集,实现日志的集中管理和存储。支持解析任意格式、任意来源的日志,通过解析规则标准化。

  • 使用无代理的方式收集日志。

  • 支持代理方式的日志收集。

关联分析:
  • 预置多种事件关联规则。

  • 定位外部威胁、黑客攻击、内部违规操作,设备异常。

  • 简单灵活定义关联规则。

实时告警:
  • 通过邮件、短信、声音对发生的告警进行及时通知,并可通过接口调用自动运行程序或脚本。

  • 通过告警策略定义,对各类风险 和事件进行及时告警或预警,提升运维效率。

日志取证分析:
  • 深入分析原始日志事件,快速定位问题的根本原因。

  • 生成取证报表,例如攻击威胁报表、Windows/Linux系统审计报表以及合规性审计报表等。

监管合规:
  • 提供Windows审计、Linux审计、PCI、SOX、ISO27001等合规性报表。

  • 支持创建自定义合规性报表

日志审计系统产品功能结构:

图:日志审计系统产品功能结构

日志审计系统的主要工作原理是,通过日志采集器,各种设备将日志推送到日志审计平台,然后日志审计平台通过日志解析,日志过滤,日志聚合等进行关联分析,从而进行告警,统计报表,也可以进行资产管理,日志检索等。

日志的转发方式:

日志转发一般可以通过:Syslog转发,Kafka转发,http转发。

日志收集一般支持:Syslog、SNMP等日志协议。

日志审计系统常见模块:

  • 日志事件获取模块:安全事件监控系统是实时掌握全网的安全威胁状况的重要手段之一。通过事件监控模块监控各个网络设备、主机系统等日志信息,以及安全产品的安全事件报警信息等,及时发现正在和已经发生的安全事件,通过响应模块采取措施,保证网络和业务系统的安全、可靠运行。

  • 资产管理模块:资产管理实现对网络安全管理平台所管辖的设备和系统对象的管理。它将其所辖IP设备资产信息按其重要程度分类登记入库,并为其他安全管理模块提供信息接口。

  • 规则库模块:规则库已支持主流网络设备、主机系统、数据库系统等,而且还应涵盖已经部署的安全系统,包括防火墙系统、防病毒系统等。并提供新日志格式适配功能,支持从安全运营中心平台接收新日志解析映射规则配置。用户可以根据该适配功能,对新日志格式进行自行适配。

  • 统计报表功能:具备强大的统计功能,可快速生成多种专业化的报表并支持自定义图表的设定集展示。

  • 权限管理模块:超级管理员可根据用户角色分配平台查看、操作各模块的权限,用户可以访问而且只能访问自己被授权的资源

日志审计平台的部署方式

硬件产品部署方式:

一般日志审计系统采用旁路部署即可,只要到达全部设备网络可通即可。

支持单机部署和分布式部署。


站在变革的十字路口,智慧医院还存在哪些建设误区?

科技创新小小鸟a 发表了文章 • 0 个评论 • 28 次浏览 • 2021-04-27 18:38 • 来自相关话题

在我国医疗信息化发展不断加速的进程上,医院作为连接医患群体、提供医疗服务的前线,似乎也走到了转型升级的十字路口。日前,以“智慧赋能·助力健康中国”为主题的2021全国智慧医院建设大会在上海召开,众多医疗从业者、云服务商、高校学者等共同聚焦医疗卫生事业,围绕智慧... ...查看全部

在我国医疗信息化发展不断加速的进程上,医院作为连接医患群体、提供医疗服务的前线,似乎也走到了转型升级的十字路口。

日前,以“智慧赋能·助力健康中国”为主题的2021全国智慧医院建设大会在上海召开,众多医疗从业者、云服务商、高校学者等共同聚焦医疗卫生事业,围绕智慧医院的建设思路展开了讨论和探索。

其中,中软国际云智能业务集团以其携手华为打造的智慧医院标杆项目“广东省第二人民医院”为例,重点提出了“全场景智慧、全要素协同、全业务运营,打造全场景智能医院”的观点,为下一代智慧医院的发展提供了诸多实践经验和建设思路。

不难发现,聚焦此次会议,伴随着产业融合趋势的来临,越来越多的医院走上了智能化转型的道路,而同时也有更多的云服务商投身其中,为智慧医院建设提供一体化解决方案,共同推动医疗信息化改革。

那么,在这样的驱动下,我国智慧医院是否能迎来一个光明的未来呢?

1 传统医院,是否到了变革的十字路口?

未来如何,得先确定一下未来是否会来,是否存在足够的条件支持传统医院走上转型升级的道路。

当前,我国正处于智慧医院建设的第一阶段。随着疫情防控的常态化开展、十四五规划的逐步落实,聚焦智慧医疗改革必然成为未来社会发展的关键方向。

事实上,近两年来,我国也一直在政策层面对智慧医院建设施加正向推力。在2018年,国务院办公厅便印发了《关于促进“互联网+医疗健康”发展的意见》,明确指出到2020年,二级以上医院普遍提供分时段预约诊疗、智能导医分诊、候诊提醒、检验检查结果查询、诊间结算、移动支付等线上服务,积极发展“互联网+医疗健康”,引入优质医疗资源,提高医疗健康服务的可及性。

因此,有了明确的发展方向,伴随着AI、5G、云计算、大数据等前沿技术的快速发展和深化应用,“互联网+”也顺势迭代升级至“AI+”。更多新技术的底层支持,促使医疗信息化改革面向医院场景实现了更全面的智能化转型。

在广东省第二人民医院,中软国际云智能业务集团携手华为通过整合AI、云、大数据等前沿技术,打造并应用了医院智慧运营中心HOC大脑,使得院区内防疫、安防、消防等各环节实现了一屏精准化管理,突破了传统医院的管理模式。

而这样的实践,也使得智慧医疗的市场加速扩容。据中国电子学会统计的最新数据显示,到2021年医疗人工智能行业市场规模将会达到75.3亿元。那么,新需求的增长吸引着更多医疗从业者和云服务商涌向这个市场,商业化的驱动使得智慧医院的建设进入一个更加良性的发展阶段。

目前,中软国际云智能业务集团等云服务商正是在这样的发展下,积极参与到智慧医院的建设,通过技术和运营的方式和传统医院联合,共同推动医疗的信息化改革。

总的来说,在十四五规划的开局之年,智慧医院建设的各方面条件都有了相对比较成熟的基础,政策上的正向推力、技术上的应用落地和市场上的商业驱动等等,都促使着智慧医院必然会成为未来发展的大趋势。

2 智慧医院,还存在哪些建设误区?

趋势可以判断,而过程又该如何展开?智慧医院建设本身就是一个驳杂多元的系统,且不说传统医院体系交叠复杂,就智能化的建设而言也面临着多方协调、长期投入的难点。

在这个道路上,注定不会简单。在此,我们或许可以从三个关键词来思考一下,智慧医院发展还存在着哪些建设上的误区?

1.     底座:光想着“建高楼”,不可忽视了“打基础”。

很多时候,传统行业的智能化升级不能只是原地起高楼,光想着在传统模式上部署项目、落实技术是不行的,新旧结合意味着流程重塑,还必须得统筹全局,打好基础。

比如,如果只是在原来的各个节点部署新系统,是否可以建设好智慧医院?答案是不能的。对此,中软国际云智能业务集团选择了以HOC大脑+八大应用+数字平台为主的顶层设计,实现院区从门诊到住院、从诊疗到科研、从患者体验到医护效率的全智能化覆盖,赋能医院从粗放式向精细化转变。

同时,“打基础”还不只是顶层设计的问题,从长远目标来看,更是整个医疗系统的全方位转型落实。因此,中软国际云智能业务集团在打造智慧院区解决方案上,重点也将云、AI、5G、大数据等技术应用于医、教、研、管等各个领域,做好各方面的转型工作。

以“研”来说,医药研发是日常患者并不关注的领域,但确是推动医疗行业发展的基础。将新技术应用于基础领域,正是立足在医疗行业的全局发展,从最核心的环节做好技术赋能。也只有把基础打好了,才能保证智慧医院的“高楼”建设稳定而又高效,这便是“底座”的价值。

2.    场景:哪些群体才是智慧医院的服务对象?

医院是面向患者的服务场景,而智慧医院不然,其需要面向患者,也需要面向医护人员、医院管理者、医联体等多个主体。因此,明确哪些群体才是智慧医院的服务对象至关重要。

如果无法兼顾多个服务对象,智慧化升级终究是不完整的,智慧医院也就名不副实。这也是为什么中软国际云智能业务集团致力于打造“全场景智能医院”的初衷。

面向患者,需要打造全流程智能就医,优化就诊体验;面向医护,需要打造智能工作站,辅助贯穿诊疗全流程;面向医院管理者,需要打造全方位可视、可管、可控的服务能力,推动精细化管理,等等。中软国际云智能业务集团在打造全场景智能医院时,正是明确了这些服务对象,进而针对特定的群体开展系统部署,提供全面的智能化升级服务。

中软国际云智能业务集团执行总裁孙佳韡认为,“这段时期,人们更多是给数字经济未来的腾飞建设一条相互连接公路,只有“路”修通了,数字经济才有了基础,人们才会真正认识到其所带来的新机会。”

很显然,对于智慧医院建设而言,需要搭建的正是让每一个对象触达智慧医院的“公路”,只有每一个人脚下的“路”修通了,智慧医院的成果才能真正惠及到社会。

3.    生态:”单打独斗”已成过去式,协同的价值可以发挥几何?

总的来说,智慧医院建设一个既宽泛也很有纵深的工程,这也决定了其必然需要一个长期的投入和布局。因此,在智慧医院的建设历程上,仅是一个人的单打独斗很乏力,更多是基于生态联合,整合优势才能撑起医院系统全方位的智能化。

因此,中软国际云智能业务集团在打造全场景智能医院的过程,也携手华为强强联合推动医疗信息化改革。此次2021全国智慧医院建设大会的召开,也正是希望在经验交流中集思广益,让更多的从业者看到合作的希望,通过生态整合来推动智慧医院的落地。

思维导向驱动发展进程。中软国际云智能业务集团所构想的“全场景智能医院”既然要全面,就必然需要连同更多的生态伙伴,在专业分工下打造完整的医院智能系统。

事实上,伴随着传统产业的智能化改革,这样生态路径会是常态,也是主流。这也意味着,智能化升级考验的不仅是自家的能力,也挑战者生态的水平,谁能携手更多更优质的生态伙伴,谁就拥有更大的市场优势。

3 下一代更智慧的医院,还有多远?

目前,我国智慧医院建设才刚刚起步,从三个关键词来看,建设者需要避免进入“基础不牢”、“服务对象不清晰”、“个人单打独斗”的误区。而做好底座建设、场景布局和生态合作三个层面的工作,也意味着智慧医院并非一蹴而就。

但也并不是遥不可及。中软国际云智能业务集团携手华为广东省第二人民医院打造智慧院区项目已取得了不错的反馈。据官方数据显示,基于智慧化升级,院区安保成本下降15%,能耗成本下降10%,就医时间成本减少了0.5h。

可见,在稳步的建设推动下,智慧医院相较于传统医院,正在持续优化院区管理和就医体验。只要伴随着前沿技术的深化应用和流程设计的科学部署,智慧医院将会从更多的层面推动医院系统和诊疗服务实现更便捷、高效的发展。

而在这个过程,更多的建设者需要看到智慧医院发展的误区,能笃定智慧医院的未来,并从前沿技术、诊疗流程、管理领域、生态伙伴等多个层面切实推动医院转型升级,才能迎来一个更智慧的未来医院。


从“十四五”规划看去中心化云计算的崛起

科技创新小小鸟a 发表了文章 • 0 个评论 • 33 次浏览 • 2021-04-27 18:12 • 来自相关话题

云计算发展如火如荼,但这个“云计算”却实际上被默认为“中心化”云计算,即集中化、统一归属的远程集群计算。然而,一种“去中心化”云计算正在快速兴起,成为不可忽视的力量。在十四五规划纲要中,2025年我国的数字经济核心产业增加值占GDP比重要从7.8%提升至10%... ...查看全部

云计算发展如火如荼,但这个“云计算”却实际上被默认为“中心化”云计算,即集中化、统一归属的远程集群计算。然而,一种“去中心化”云计算正在快速兴起,成为不可忽视的力量。

在十四五规划纲要中,2025年我国的数字经济核心产业增加值占GDP比重要从7.8%提升至10%,这其中,云计算、区块链等技术毫无疑问是建设数字中国的重要技术载体,在推动政企数字化变革、激发数字化技术与商业模式创新等方面有关键的作用。

区块链底层技术+云计算模式形成的“去中心化云计算”在产业政策导向下,大量玩家纷纷入局,以期在这个新领域占据先机、成为另一种形式的云计算巨头。

这包括想要成为“永不宕机的阿里云”的AELF区块链项目,号称要对标谷歌云、微软云的DADI区块链项目,以及自称“全球首家泛载雾计算平台”的博纳云(BonusCloud)、定位自己为“全球首个去中心化的云计算市场”的Akash(主要为DeFi提供去中心化云服务,即DeCloud)等。

而其中,有不少项目或企业已经进入实质性的应用阶段,取得了不错的市场成绩。例如宣称要做“去中心化云计算一站式服务领军者”的安迈云,其产品和解决方案在很多企业中得到落地应用。

以去中心化技术重构信任与安全,重塑传统集中式云计算的业务模型和资源分配结构,去中心化云计算正在推动数字经济更好、更快速地实现。

1 数字经济被提到新的高度,倒逼去中心化云计算快速发展?

一边是数字经济被列入未来宏观发展规划,另外一边,在数字经济推进过程中,很多挑战也逐渐显露出来,尤其是作为存储与计算发展主要力量的云计算,在应用到政企数字化转型过程中,出现很多亟待优化和解决的问题。在十四五规划的单列篇章五中,就对云计算发展有专门的论述,包括加快云操作系统迭代升级,推动超大规模分布式存储、弹性计算、数据虚拟隔离等技术创新,提高云安全水平等。

从这个意义上看,去中心化云计算的发展,首先通过帮助政企更好地实现数字化转型,契合了数字经济进一步发展的特征,从而实现了快速发展,这某种程度上是需求倒逼的结果。

1、成本:既要关注当下业务需求,更需要关注扩展需要

政企数字化越是往深处走,中心化云计算在成本方面的挑战就是凸显:如果说云计算相对于本地部署在成本上有巨大优势,那么当政企数字化走向深入后,复杂计算、大规模计算、海量数据存储等将同样给企业带来越来越沉重的负担。

较为典型的,如工业互联网建设,企业不得不为此在云计算上投入巨大的存储和计算成本。

而去中心化云计算由于采用的是分布式、不需要大批量基础设施建设的存储和计算节点,在成本上有巨大的优势,那些存储和计算规模庞大、任务繁重的企业,采用去中心化云计算将直接节约成本。

更进一步来看,由于去中心化的技术特性(个体节点、充分细分),当企业想要将存储和计算规模扩大(这是常态)时,在边际成本上也将变得更低。

如此,在门槛更低的情况下,政企组织接入云计算变得更容易,数字经济的规划落地也就扫除了参与度的障碍。

2、安全:既需要总体运行的安全,更需要个体数据的安全

云计算,或者说中心化云计算似乎生来就带有安全方面的挑战。

一方面,由于存储、计算的集中化,大量政企组织依赖一个平台,当中心化的平台出现运行问题,就会殃及几乎所有被服务方——中心化云计算的规模做得越大,这种运行方面安全问题的隐忧就越大。那些大型云计算平台的宕机事件每每都能成为业界“大新闻”,100%地把自己的身家性命压在了第三方服务器上的企业很难承受这样的宕机事故,但事故又层出不穷,受限于中心化的机制难以在根本上避免。

这时候,去中心化云计算的优势显露出现,分散的节点使得去中心化云计算理论上可以做到永不宕机,这是一种机制上的先天优势。

另一方面,在数据的归属上,客户与中心化云计算平台之间存在微妙的关系,上传的文件、处理业务的数据沉淀如何保证隐私性和安全性是政企客户常常考虑的问题,很多时候数据安全的保障甚至只能靠中心化平台的“自觉”,这显然不符合数字经济时代的需要。

3、体验:既需要灵活多样的弹性服务,更需要定制化的专业服务

尽管传统中心化云计算一直在进行弹性存储和计算方面的技术更新,但这种弹性往往只是尽可能拟合现实需要,企业实际应用时,在需要变动十分复杂时,还是会不可避免地出现配置资源不足或浪费的情况。

这是由于传统中心化云计算一般都是先有订单再有服务,资源的配置需要系统的划分,弹性调整需要极为复杂的技术来实现,往往无法做到真正的“要多少、给多少、收多少费用”。

而去中心化云计算由于节点被最大程度分散,在低颗粒度的情况下,弹性服务的提供上更有潜力。

此外,数字化转型走向深入后,很多政企组织对定制化服务的需求越来越显著,契合自身需要的产品和解决方案变得更重要,但在中心化情况下,这可能是属于大客户才能享有的待遇。

在去中心化云计算这里,情况或能够得到改善,例如,安迈云构建的去中心化云计算产品体系中,类似IPFS基础设施解决方案这种服务,能够很好地利用去中心化的高可用性、资源独享、部署灵活等特征,为客户定制优化的分布式存储的解决方案。

总得看来,在宏观政策导向下,“传统”中心化云计算与“政策期望”之间的差距,正在被去中心化云计算所弥合。

2 区块链价值落地,给去中心化云计算带来新的价值想象空间?

不可忽视的是,去中心化云计算本质可以算是区块链技术的一个重要应用,从区块链的角度看,它则是中国乃至全球区块链产业蓬勃发展的代表,成为业界所期待的有效落地项目之一。

而正是从这个角度,而不是单纯从云计算角度看,去中心化云计算又可以为数字经济带来新的价值想象空间。

1、数字资产流转新蓝海,需要新的基础设施

数据隐私的保护其实背后暗含另一层意义,即数据资产的归属与处置问题。隐私得到很好的保护,会使得用户将数据的价值控制在自己手中,从而催生商业模式创新。

在区块链技术的加持下,去中心化云计算中的数据,有机会完成中心化云计算难以完成的数据资产确权等工作,用户在链上可以便捷、安全地向第三方有偿分享数据信息,从而让自己的数据池变成某种数字资产,换取收益。

在这种情况下,国家大力倡导的数字经济,在数据底层原料层面将变得更加有活力。

2、多样性计算各有所长,计算与硬件匹配才能大大提升效率

云计算的底层架构,在传统的X86之外,近年来ARM等架构的计算芯片崛起,且厂商众多。在分布式云计算中,由于参与成为节点的硬件各异,使得用户总能够根据自身的需要,在链上找到对应的、能够最大程度发挥芯片架构优势加速运行效率的计算硬件,使得计算找到最好的硬件匹配。

换言之,用户不但可以快速进行横向的计算能力扩展,也更容易找到效果更好、成本控制更优的多样化计算硬件。

而对比来看,很多中心化云计算平台还在为了多样性计算的兼容而投入大量资源。

3、特殊数字场景凸显“既要……又要……”难题,亟待解决

随着数字经济走向全领域、全场景,很多过去被认为是云计算“禁区”的特殊数字场景,也不得不顺应时代需求进行变革升级,金融场景最为典型。

出于监管的需要,过去在金融领域,数据必须放在本地,很难进行远程外部机房的连接访问工作,这影响了计算效率的发挥,让银行等核心金融机构在数字化这件事上似乎总是慢半步。

现在,去中心化云计算借助安全、保密难以被攻破的区块链技术,能最大程度保证金融数据安全,同时扩展更多存储与计算服务。

类似的场景还有更多,这些最难的堡垒打下来后,数字经济才能真正实现落地。

3 搭上趋势快车,但去中心化云计算“颠覆”却不“替代”?

毫无疑问,与传统的云计算相比,去中心化云计算是一种模式上的颠覆,是区块链技术的重要落地应用,最大程度契合了宏观政策对云计算推动数字经济发展的期盼。

但是,必须看到的是,同样在政策导向下,去中心化云计算却并不对传统中心化云计算形成替代,只是在补足后者无法很好地满足的领域,共同服务于数字经济时代。所以,中心化与去中心化云计算的并存将成为一种常态,有业内人士认为,二者将凭借各自优势分享市场(例如,中心化云计算在社交、电商这类实时、复杂、高频应用中有天然优势),各占50%的份额。

甚至,去中心化云计算中的IPFS作为一个面向全球的、点对点的分布式版本文件系统,其有不少节点使用的是微软、谷歌、阿里云等公司的云服务器(这并不违背去中心化原则,中心化的平台所提供的存储和计算服务只作为一个节点存在),这种特殊的关系证明了二者的共存将是未来的常态。

当去中心化云计算平台逐步发展起来,可以发现,它们并不是搅局者,而是为云计算多走出一条路、创造“另一个未来”。但无论如何,这个市场都足够广阔,新的巨头料将出现,在经历缓慢发展后(IPFS去中心化的核心组件开发已经8年之久),去中心化云计算的爆发可能即将来临。


什么是充血模型?什么又是贫血模型?

科技创新柠檬^ 发表了文章 • 0 个评论 • 35 次浏览 • 2021-04-27 17:23 • 来自相关话题

贫血模型即事务脚本模式充血模型即领域模型模式贫血模型最早广泛应用源于EJB2,最强盛时期则是由Spring创造,把“行为”(逻辑、过程)“状态”(数据,对应到语言就是对象成员变量)分离到不同的对象中:只有状态的对象就是所谓的“贫血对象”(常称为VO——Valu... ...查看全部
  • 贫血模型即事务脚本模式

  • 充血模型即领域模型模式

贫血模型

最早广泛应用源于EJB2,最强盛时期则是由Spring创造,把

  • “行为”(逻辑、过程)

  • “状态”(数据,对应到语言就是对象成员变量)

分离到不同的对象中:

  • 只有状态的对象就是所谓的“贫血对象”(常称为VO——Value Object)

  • 只有行为的对象就是我们常见的N层结构中的Logic/Service/Manager层(对应到EJB2中的Stateless Session Bean)。(曾经Spring的作者Rod Johnson也承认,Spring不过是在沿袭EJB2时代的“事务脚本”,也就是面向过程编程)

贫血领域模型是一个存在已久的反模式,目前仍有许多拥趸者。Martin Fowler曾经和Eric Evans聊天谈到它时,都觉得这个模型似乎越来越流行了。作为领域模型的推广者,他们觉得这不是一件好事。

贫血领域模型的基本特征是:它第一眼看起来还真像这么回事儿。项目中有许多对象,它们的命名都是根据领域来的。对象之间有着丰富的连接方式,和真正的领域模型非常相似。但当你检视这些对象的行为时,会发现它们基本上没有任何行为,仅仅是一堆getter/setter。其实这些对象在设计之初就被定义为只能包含数据,不能加入领域逻辑。这些逻辑要全部写入一组叫Service的对象中。这些Service构建在领域模型之上,使用这些模型来传递数据。

这种反模式的恐怖之处在于,它完全和面向对象设计背道而驰。面向对象设计主张将数据和行为绑定在一起,而贫血领域模型则更像是一种面向过程设计,Martin Fowler和Eric在Smalltalk时就极力反对这种做法。更糟糕的时,很多人认为这些贫血领域对象是真正的对象,从而彻底误解了面向对象设计的涵义。

如今,面向对象的概念已经传播得很广泛了,而要反对这种贫血领域模型的做法,还需要更多论据。贫血领域模型的根本问题在于,它引入了领域模型设计的所有成本,却没有带来任何好处。最主要的成本是将对象映射到数据库中,从而产生了一个O/R(对象关系)映射层。只有当你充分使用了面向对象设计来组织复杂的业务逻辑后,这一成本才能够被抵消。如果将所有行为都写入到Service对象,那最终你会得到一组事务处理脚本,从而错过了领域模型带来的好处。正如martin在企业应用架构模式一书中说到的,领域模型并不一定是最好的工具。

将行为放入领域模型,这点和分层设计(领域层、持久化层、展现层等)并不冲突。因为领域模型中放入的是和领域相关的逻辑——验证、计算、业务规则等。如果你要讨论能否将数据源或展现逻辑放入到领域模型中,这就不在本文论述范围之内了。

一些面向对象专家的观点有时会让人产生疑惑,他们认为的确应该有一个面向过程的服务层。但是,这并不意味着领域模型就不应该包含行为。事实上,service层需要和一组富含行为的领域模型结合使用。

Eric Evans的Domain Driven Design一书中提到:

  • 应用层(即Service层)

描述应用程序所要做的工作,并调度丰富的领域模型来完成它。这个层次的任务是描述业务逻辑,或和其它项目的应用层做交互。这层很薄,不包含任何业务规则或知识,仅用于调度和派发任务给下一层的领域模型。这层没有业务状态,但可以为用户或程序提供任务状态。

  • 领域层(或者叫模型层)

表示业务逻辑、业务场景和规则。该层次会控制和使用业务状态,即使这些状态最终会交由持久化层来存储。总之,该层是软件核心。

服务层很薄——所有重要的业务逻辑都写在领域层。他在服务模式中复述了这一观点:如今人们常犯的错误是不愿花时间将业务逻辑放到合适的领域模型中,从而逐渐形成面向过程的程序设计。

我不清楚为什么这种反模式会那么常见。我怀疑是因为大多数人并没有使用过一个设计良好的领域模型,特别是那些以数据为中心的开发人员。此外,有些技术也会推动这种反模式,比如J2EE的Entity Bean,这会让我更倾向于使用POJO领域模型。

总之,如果你将大部分行为都放置在服务层,那么你就会失去领域模型带来的好处。如果你将所有行为都放在服务层,那你就无可救药了。

优点

简单

  • 对于只有少量业务逻辑的应用来说,使用起来非常自然

  • 开发迅速,易于理解

  • 注意:也不能完全排斥这种方式

缺点

无法良好的应对复杂逻辑

  • 比如收入确认规则发生变化,例如在4月1号之前签订的合同要使用某规则…..

  • 和欧洲签订的合同使用另外一个规则…..

充血模型

面向对象设计的本质:“一个对象是拥有状态和行为的”,比如一个人:

  • 他眼睛什么样鼻子什么样这就是状态

  • 人可以去打游戏或是写程序,这就是行为

为什么要有一个“人Manager”这样的东西存在去帮人“打游戏”呢?举个简单的J2EE案例,设计一个与用户(User)相关功能。传统的设计一般是:

  • 类:User+UserManager

  • 保存用户调用:userManager.save(User user)

充血的设计则可能会是:

  • 类:User

  • 保存用户调用:user.save()

  • User有一个行为是:保存它自己

其实它们没有什么特别适用的方向,个人更倾向于总是使用充血模型,因为OOP总是比面向过程编程要有更丰富的语义、更合理的组织、更强的可维护性—当然也更难掌握。因此实际工程场景中,是否使用,如何使用还依赖于设计者以及团队充血模型设计的理解和把握,因为现在绝大多数J2EE开发者都受贫血模型影响非常深。另外,实际工程场景中使用充血模型还会碰到很多很多细节问题,其中最大的难关就是“如何设计充血模型”或者说“如何从复杂的业务中分离出恰到好处且包含语义的逻辑放到VO的行为中”。

如果一个对象包含其他对象,那就将职责继续委托下去,由具体的 POJO 执行业务逻辑,将策略模式更加细粒度,而不是写 ifelse。


分页场景(limit, offset)为什么会慢?

科技创新大神庵 发表了文章 • 0 个评论 • 38 次浏览 • 2021-04-27 17:11 • 来自相关话题

从一个问题说起五年前发现分页场景下,mysql请求速度非常慢。数据量只有10w的情况下,select xx from 单机大概2,3秒。我就问我导师为什么,他反问“索引场景,mysql中获得第n大的数,时间复杂度是多少?”答案的追寻确认场景假设status上面... ...查看全部
从一个问题说起

五年前发现分页场景下,mysql请求速度非常慢。数据量只有10w的情况下,select xx from 单机大概2,3秒。我就问我导师为什么,他反问“索引场景,mysql中获得第n大的数,时间复杂度是多少?”

答案的追寻
确认场景

假设status上面有索引。select * from table where status = xx limit 10 offset 10000。会非常慢。数据量不大的情况就有几秒延迟。

小白作答

瞎猜了个log(N),心想找一个节点不就是log(N)。自然而然,导师让我自己去研究。

这一阶段,用了10分钟。

继续解答

仔细分析一下,会发现通过索引去找很别扭。因为你不知道前100个数在左子树和右子数的分布情况,所以其是无法利用二叉树的查找特性。通过学习,了解到mysql的索引是b+树。

看了这个图,就豁然开朗了。可以直接通过叶子节点组成的链表,以o(n)的复杂度找到第100大的树。但是即使是o(n),也不至于慢得令人发指,是否还有原因。

这一阶段,主要是通过网上查资料,断断续续用了10天。

系统学习

这里推荐两本书,一本《MySQL技术内幕 InnoDB存储引擎》,通过他可以对InnoDB的实现机制,如mvcc,索引实现,文件存储会有更深理解。

第二本是《高性能MySQL》,这本书从着手使用层面,但讲得比较深入,而且提到了很多设计的思路。

两本书相结合,反复领会,mysql就勉强能登堂入室了。

这里有两个关键概念:

  • 聚簇索引:包含主键索引和对应的实际数据,索引的叶子节点就是数据节点

  • 辅助索引:可以理解为二级节点,其叶子节点还是索引节点,包含了主键id。

即使前10000个会扔掉,mysql也会通过二级索引上的主键id,去聚簇索引上查一遍数据,这可是10000次随机io,自然慢成哈士奇。这里可能会提出疑问,为什么会有这种行为,这是和mysql的分层有关系,limit offset 只能作用于引擎层返回的结果集。换句话说,引擎层也很无辜,他并不知道这10000个是要扔掉的。以下是mysql分层示意图,可以看到,引擎层和server层,实际是分开的。

直到此时,大概明白了慢的原因。这一阶段,用了一年。

触类旁通

此时工作已经3年了,也开始看一些源码。在看完etcd之后,看了些tidb的源码。无论哪种数据库,其实一条语句的查询,是由逻辑算子组成。

逻辑算子介绍 在写具体的优化规则之前,先简单介绍查询计划里面的一些逻辑算子。

  • DataSource 这个就是数据源,也就是表,select * from t 里面的 t。

  • Selection 选择,例如 select xxx from t where xx = 5 里面的 where 过滤条件。

  • Projection 投影, select c from t 里面的取 c 列是投影操作。

  • Join 连接, select xx from t1, t2 where t1.c = t2.c 就是把 t1 t2 两个表做 Join。

选择,投影,连接(简称 SPJ) 是最基本的算子。其中 Join 有内连接,左外右外连接等多种连接方式。

select b from t1, t2 where t1.c = t2.c and t1.a > 5 变成逻辑查询计划之后,t1 t2 对应的 DataSource,负责将数据捞上来。上面接个 Join 算子,将两个表的结果按 t1.c = t2.c连接,再按 t1.a > 5 做一个 Selection 过滤,最后将 b 列投影。下图是未经优化的表示:

所以说不是mysql不想把limit, offset传递给引擎层,而是因为划分了逻辑算子,所以导致无法直到具体算子包含了多少符合条件的数据。

怎么解决

《高性能MySQL》提到了两种方案

方案一

根据业务实际需求,看能否替换为下一页,上一页的功能,特别在ios, android端,以前那种完全的分页是不常见的。这里是说,把limit, offset,替换为>辅助索引(即搜索条件)id的方式。该id再调用时,需要返回给前端。

方案二

正面刚。这里介绍一个概念:索引覆盖:当辅助索引查询的数据,只有id和辅助索引本身,那么就不必再去查聚簇索引。

思路如下:`select xxx,xxx from in (select id from table where second_index = xxx limit 10 offset 10000)“ 这句话是说,先从条件查询中,查找数据对应的数据库唯一id值,因为主键在辅助索引上就有,所以不用回归到聚簇索引的磁盘去拉取。再通过这些已经被limit出来的10个主键id,去查询聚簇索引。这样只会十次随机io。在业务确实需要用分页的情况下,使用该方案可以大幅度提高性能。通常能满足性能要求。


继Elastic怒喷云服务商白嫖之后,AWS 终于退出ES的开源分支:OpenSearch!

科技创新大神庵 发表了文章 • 0 个评论 • 34 次浏览 • 2021-04-27 17:11 • 来自相关话题

一直关注DD的朋友应该还记得,今年年初时Elastic公司曾宣布改变其名下的开源协议,而对此AWS(Amazon Web Services——Amazon云服务)就随即表示自己将在仍为开源状态的 Elasticsearch 和 Kibana( 7.10 版本)... ...查看全部

一直关注DD的朋友应该还记得,今年年初时Elastic公司曾宣布改变其名下的开源协议,而对此AWS(Amazon Web Services——Amazon云服务)就随即表示自己将在仍为开源状态的 Elasticsearch 和 Kibana( 7.10 版本)创建分支,今后自己来维护这个分支,做到真正的开源。

转眼间已经过了快三个月,当初的这个真正的开源事件就在近日有了下文。

4月12号,AWS官方宣布推出 OpenSearch 项目!

根据AWS的官方介绍,OpenSearch 项目由OpenSearch和OpenSearch Dashboards组成,这两项的确也都是基于当初所说的Elasticsearch 和 Kibana( 7.10.2 版本)。

项目均采用Apache License 2.0 开源许可协议,功能完成度也不少,包括像企业安全、告警、机器学习、SQL、索引状态管理等,应有尽有。

而针对Elasticsearch之前的改变以及自己的真开源讲法,AWS表示OpenSearch虽然时基于Elasticsearch,但是删除了其中和Elastic有关的商业许可证限制、代码、商标等,在采用了Apache License 2.0 之后,OpenSearch可以让每个用户都毫无负担的构建和创新,而不用再担心一些贡献之外的问题。

同时,AWS还宣布现有的 Amazon Elasticsearch Service,将会变更名号,成为一个崭新的Amazon OpenSearch Service!

更名之后的Amazon OpenSearch Service,想必是为了摆脱和Elasticsearch的关联,在不影响正在运营业务的前提下,还会提供一系列可供部署和运行的开源引擎,包括当前可用的 19 个版本的 Elasticsearch(7.9 和更早版本、近期推出的 7.10)以及新版本的 OpenSearch。

为了满足现有用户的使用需要,AWS还宣布未来的Amazon OpenSearch Service API 将与现有服务 API 完美兼容,还会为用户提供将现有 Elasticsearch 6.x 和 7.x 托管集群迁移至 OpenSearch 的无缝升级路径。

可能在未来的几周内,我们就能见到AWS发布 Beta 版本,根据AWS的展望,预计在2021年中期发布稳定版并投入生产环境使用。

随着AWS的声明,不少公司都纷纷站队表示支持,像红帽、SAP、Capital One 和 Logz.io 都是其坚定的盟友。

红帽表示:

我们感谢亚马逊对开放搜索的承诺,我们很高兴看到亚马逊继续支持开源

SAP表示:

SAP客户期望一个统一的、以业务为中心的、开放的SAP业务技术平台。OpenSearch提供了一个真正的开源途径和社区驱动的方法来推动这一进程。

Capital One说到:

我们非常支持OpenSearch项目,因为它将使我们能够更好地控制和自主选择数据平台,同时保留开放源代码许可证提供的自由。

而第一个站出来吐槽Elastic公司的Logz.io则发言:

我们承诺与AWS和社区其他成员合作,创新并使世界各地的每个组织都能享受这些关键的开源项目带来的好处。

那到底AWS的OpenSearch能不能达到大家的预期呢?我们拭目以待!


其他职业越老越值钱,程序员越老越贬值?

科技创新小小鸟a 发表了文章 • 0 个评论 • 44 次浏览 • 2021-04-16 14:47 • 来自相关话题

前言今天一早,看到NBA交易消息中提到:小加索尔与洛杉矶湖人队签下两年老将底薪合同。业界评论一致认为湖人这次在中锋这个位置进行了补强,甚至有人认为湖人是捡了个大便宜。小加索尔作为一个85年出生的球员,在NBA赛场上已经是处于职业生涯晚期的球员,为什么还这么受关... ...查看全部

前言

今天一早,看到NBA交易消息中提到:小加索尔与洛杉矶湖人队签下两年老将底薪合同。业界评论一致认为湖人这次在中锋这个位置进行了补强,甚至有人认为湖人是捡了个大便宜。

小加索尔作为一个85年出生的球员,在NBA赛场上已经是处于职业生涯晚期的球员,为什么还这么受关注呢?其实每年NBA交易期都会有这样类似的情况,一些早已功成名就的老将,不在意薪水的多少,只想加入一只有争冠实力的球队,并且往往他们的经验会让球队受益匪浅,关键时刻往往会帮助球队获得胜利。正如我们华夏民族一直流转的那句“家有一老,如有一宝”。

每一个职业每一个行当,一代代的经验传承,造就了中华民族五千年的文化荟萃,但是现在似乎程序员这个职业有些另类,别的职业都是越老越值钱,唯独程序员,在众人的眼中越老越容易失业?越老越贬值?

那究竟是什么原因造成了这个现象呢?让我们一起看看知友们都是怎么说的吧

做程序员这些年,我一直在思考一个问题,就是:

就互联网公司而言,对于公司好的发展逻辑其实是跟对于个人来说好的发展逻辑似乎是有冲突的。

对于一个大公司来说,一个新员工进来,首先要做的是什么?

学习遵守公司的流程规范,让自己的工作内容和工作方式都以一种标准化的方式进行。

哪怕你做了某个很好用的工具,或者发现了做这件事的更高效的方法。

那么在得到上级认可之后,你要干什么?

把这个东西整理成标准的流程,文档,以提高后面新入职的同事的工作效率。

为的是什么?

为的是哪怕有一天你不在这个公司了,你所做的这一部分工作也能很快地找到另外一个人来代替。

当然,然后还有进行项目开发时对于代码和文档的各种规范和要求,越是大公司,在这方面的要求越是严格。

为的是什么?

为的是哪怕你作为这个项目的核心开发者,但是如果有一天你主动离职了,或者年龄大了被公司裁了,这个项目依旧可以正常地运行迭代下去。

这确实是对于公司发展来说最好的逻辑。

但是问题是,这对我们作为员工的个人来说,可能并不是一个好的逻辑。

如果一个公司想要做大,想要走的远,那么他们就需要通过标准化,规范化的流程来把个人因素变动所带来的的影响降到最低。

而在里面作为的螺丝钉的程序员,除了写代码完成业务功能以外,还要把代码写的尽量让大家都能看懂,让后来人能轻易接手。

但这也为他后续被更年轻,更能996的程序员取而代之,埋下了伏笔。

而在某些传统行业,则不是这样的。

尤其是有些老一辈的手艺人,确实是越老越吃香,甚至是一个匠人到了六七十岁,还有人愿意把自家孩子送到这个匠人门下当学徒,学习手艺。

难道是因为这个行业真的有什么常人难以学会的知识或是技能,哪怕钻研了五六十年,还是有着很大的提升空间。

以至于研究了50年的手艺人,就真的比研究了30年的,要高好几个档次,所以大家才都青睐那个更老的手艺人吗?

也不一定。

也有可能是人家只是有几个压箱底的绝活,但是这个绝活,在这个手艺人临终之前,都不会轻易地交给自己的徒弟,更不要说是新入行的同事了。

毕竟人家是打算靠这点绝活,吃一辈子饭的,如果随随便便就交给徒弟,那师傅不就饿死了吗?

所以说,明白了吗?

为什么有些职业是越老越吃香,而程序员不是越老越吃香?

因为互联网公司的逻辑是:”虽然我需要程序员来帮我开发软件,但是我更需要的是这个软件离了他之后,依然可以好好地运行,所以说我会竭尽全力地来保证流程的规范化,代码的可读性以及业务逻辑的文档化。“

这样一来,即使程序员开发出了某个发展很好的项目,但是在这个项目进入稳定生产之后,也跟他没有太大关系了。

他并不能靠对着某个项目的理解,而吃一辈子饭,因为公司的规范要求他把所有有关这个项目的理解,都整理成文档,模型,和代码注释。

他要么抓住某个机会成为管理层,拿到公司股份,要么不断跟进学习日新月异的新兴技术,要么,就只能等自己老了,精力和体力都比不过年轻人的时候,被更加年轻的程序员所取代。

从这个角度上看,公司和程序更像是一个生命,而前赴后继的程序员们,只是不断往这个生命里面注入动力的干电池而已。


自由飞的想法

大部分的中国企业,就没把程序员当做“脑力劳动者”,而是当做“体力劳动者”在用!

996是福报啊!过了35岁,搬不动砖了,996都没你的份。

我以前看报道,说“中国航天”深化改革啥啥啥的,其中一个成果就是“队伍平均年龄28.6(大概吧,总之很年轻)岁”,然后今年火箭已经炸了三次了。——这事我就随口一说,究竟什么原因炸的,炸得好不好,应该不应该,我不是行内人士,大家不用给我上课,实打实的说,我也不关心。

但以我一个快40的老码农而言,不说别人,就说我自己,我非常肯定确定以及一定:

我的能力从来没有贬值。恰恰相反,随着经验的积累,我的能力与日俱增。

我相信,就算不是全部,但很多老码农都会有这种感觉。

新东西学不动,那是懒得学!工作中用不到的,我学他干嘛?真要学的时候,分分钟捡起来,比你刚入行的菜鸟不知道快多少倍。

而且会倒腾个新技术就算有能力了?呵呵,

除了高质量代码生成以外,还有很多其他需要日积月累的技能,譬如全面审查需求,妥善安排进度,快速bug fix……

但是,企业关心这些么?

不过是搬砖的而已,能把砖搬过去就完事了,还管你怎么搬?

外包单位就不说了,卖出去一个是一个,关键是挣差价,你的工资是成本,当然越低越好。

互联网公司,钱烧得霍霍的,产品急着上线呢!还管你代码质量,只管你能加班不?!屎一样的代码糊上去再说,美其名曰“及时反馈快速迭代”……

软件公司……等等,中国有软件公司么?反正除了屈指可数的那几家,目之所及真能赚钱的都是骗补贴的!

明白了吧,这就是你问的为什么。

老程序员本身没有贬值,所谓贬值,是因为人力市场的需求。

怎么办?凉拌!

唉,希望未来能有更多脚踏实地的、以产品质量取胜的软件公司涌现出来吧!


invalid s的表述

古话说的好:“飞鸟尽,良弓藏;狡兔死,走狗烹”。

不光程序员越老越容易失业,国内一切技术行当不都这样吗?

身为技术人员,在自身职业前景上,必然要遭遇两个问题。

  • 第一个问题是他自己能控制的:你,究竟掌握了多高的技术?

是面向搜索引擎编程、只会CRUD呢;还是能够编写更高质量的代码、解决日常问题?

或者,是有充分的大中型项目设计、实施经验,甚至能够主持有一定难度的项目开发?

或者是,你能否掌握“核心科技”,挑战业界大佬?比如和思科比比网络调度算法、和Linus比比OS开发、写个数据库挑战Oracle、搞个Hadoop挑战yahoo甚至google?

可想而知,当你只会面向搜索引擎编程、只会CRUD时,你当然就是个一次性消耗品。用到三四十岁差不多也该用坏了,找个借口扔掉就是。

比赛“跑不死就往死里跑”的话,你怎么可能比得上二十来岁的小年轻呢?

想要“越老越值钱”,你就不能在年轻人的优势领域停留,你就必须不断提升自己、拓宽眼界、抬高上限——你猜Linus担心不担心失业?你猜yahoo里面编写/维护hadoop的、google里面优化big table page rank map-reduce的,他们担心不担心失业?

你究竟学会了多少,就决定了你的命运。

当你只能拼996007时,你那二十岁的身体还的确能支撑你扛大包;但到了三四十岁,哪怕没有落下一身职业病,你,还能像年轻人那样“昨天摔了一跤整条腿都紫了今天打个绷带照样活蹦乱跳”吗?

所以你失业了。那些挤走你、顶替你的,也会像你一样,在被人超负荷使用十年、落下一身病痛后滚蛋。

这就是第一个问题:你不为将来打算,急功近利透支身体996/007,所以你越老越容易失业。

你不光越老越容易失业,你还会落下一身病痛。三四十的身体甚至比不上那些会保养的、六七十的老人。你不得不掏出大量金钱来维持自己的基本生存。

如果你压根就不是什么“良弓”,凭什么阻止别人把你像垃圾一样踢开?

人无远虑,必有近忧。

  • 技术人员必将遭遇的第二个问题并不是他们能控制的。

那就是:你把自己修炼成了全世界顶尖的超高精度复合弓;但你的国家压根就没有射箭比赛。

是的,你懂操作系统内核;但中国有哪家公司在开发自己的OS?

是的,你懂数据库算法编译器优化;但中国有哪家公司能做数据库能写编译器?

如果整个社会都只能追逐那么几只半死不活的残疾兔子;你,身手矫健又有何用?

人山人海,哪里见得到兔子。

结果你还想吃多点,否则……都不够维持你的一身肌肉。

相信我。用不了多久,你也会饿成一条病恹恹的瘦狗。

那么,这就是国内醉心于技术者面对的窘境:我们压根就没有能插手基础性、支柱性软件项目的公司。唯一会的就是互联网,就是想尽办法薅用户羊毛的终端软件。

对大多所谓的“互联网公司”来说,写这种软件,“面向搜索引擎编程”“调库专家”基本够用。更高的,他们根本不敢想。

正是这种现状,使得一些缺乏眼界者压根不敢想“需要熟练使用链表算法的工作”;相反,他们会告诉你,会调库足矣、照搬互联网上搜到的代码就够用了——甚至还有在我的回答下言之凿凿、说“专家”说了,能搜到现成的代码就千万不要自己写,自己写的质量太差……

但事实是,哪怕在中国,照样有不算太少的中高端职位;这些职位的基本要求就是“不准抄网上代码”。

这是因为写出这些代码的人水平良莠不齐、写的时候也未必是按工业化/商业化标准精益求精(经常就是为了让初学者明白,所以省略了很多很多东西)——对这类中高端职位所要求的、业界top5%、top0.5%、top0.05%的、较为正规的程序员来说,这种东西说好听点叫粗制滥造,说难听点就是垃圾。

当这些人崇拜的“专家”都在顶礼膜拜网上的劣质代码时,他们的水平也就可想而知了。

眼界所限,他们完全不可能知道那些中等以上水平的程序员在做什么;在他们看来,一行代码出一堆错误是必须的——我说自己一口气写几千行不出错,他们就破口大骂:追着骂、单独开贴骂;直白的骂、阴阳怪气的骂……

这种情况,在过去是不可想象的。

在当时,别说垃圾到这种程度了,任何问题只要简单到用搜索引擎搜一搜就能解决,你敢问,就会被老手怼回去。很多论坛把“提问前应该做到什么”置顶;“STFG(Search The Fucking Goolge)”是被人普遍接受的、对小白问题的标准回复。

但现在,连网上苦口婆心的解释都读不懂、只能逐字逐句照搬现成的代码的小白敢“组团围剿”那些敢说自己能写程序的“吹牛者”。

可想而知,这种劣质码农的声音淹没一切时,这个行业会变成什么样子。

别说开拓新的市场、新的疆域了,就连抄,他们都不敢抄热乎的。

这反过来强化了劣质码农们的认知——没错,中国啊,它本来就不需要高于“面向搜索引擎编程”的装B犯。反正你们学了也没用,大家一起996,欢乐的卷起来吧。

业界整体的低水平,使得你除非在校时就憋着一口气、玩命的往世界一流水平赶;否则一旦开始工作,庸人们很快就会把你拖进自己的节奏,然后干净利落的打败——这工作你能做我也能做,我见经理满脸堆笑,你呢?书呆子。什么叫你一周抵我们一年?谁看见了?

中国技术人员地位低,原因就在于此。

一方面,因为对未来的预期过低,因此从一开始就没学到东西,就是一劣质码农;另一方面,行业整体上限不高,绝大多数人还在一门心思的拉低下限。

如此一来,未来哪还有好?

但是,这并不是全部。

事实上,正常的市场竞争下,谁落后,谁死。

因此,报社的程序员可以写出django,车库里的穷小子能折腾出google。

技术是需要积累的。只要学进去了,你的积累就绝不会是无用功。

因此,虽然按比例算,也许99.99的程序员果然是年纪大了就得滚蛋;但这不正是他们为自己做的规划吗?起初就什么都没学到、入职了也只会996没有任何技术积累——美其名曰“你需要掌握的东西,入职一个月内就能学到”。

呵呵,真这么简单全世界的大学都在坑钱不成?一个月就能学完的东西,非要把你拘禁起来教上本科四年硕士两年博士N年都还不让毕业?

你把自己当一次性用品培养,就别怪别人用旧了把你一脚踢开。

相反,那些真正知道四年本科要教你什么、知道你和世界先进水平还有多大差距的人,他们会抓住一切机会,不间断的前进,前进,继续前进。

我大一就自学到了中断服务程序、可以直接写端口命令字绕开OS/BIOS直接控制硬件;也知道动画、音频、视频、3D图形等等的基本原理;当时同学间流行一个打字游戏,但我觉得那个东西写的不好,于是花了一周不到就写了个更好的。

因此,我可以毫不含糊的吐槽——绝大多数本科生,四年连个大一水平都没学到。

比我强的车载斗量。

那么,本科四年我都甩开某些人四年,之后工作了,盯着那些比我强的紧赶慢赶,都不过勉强维持个“看得到别人尾灯”的局面;那么,一毕业就比我慢了四年、还以为一个月就学会了一生所需的全部知识的他们,有可能看见我车尾的扬尘吗?

不光我不担心自己学的东西没人要;那些比我强的没边的,照样不担心自己学的东西没人要。

甚至可以说,越是不顾那些庸人的眼光、我行我素学的精深的,越是不怕失业。因为人家的就业市场是全世界。

不是程序员这个职业越老越不值钱,而是现在的程序员处于工业革命早期煤矿工人所处的境地。

新的世界刚出现一个雏形,现在的程序员只是在用自己的血肉去充当地基和铁轨,铸造锅炉并充当点燃第一把火的燃料。

表面上看起来相对农民阶级(传统制造业),工业革命初期的产业工人收入待遇提高了很多,但是那是以压缩劳动寿命来实现的。

他们确实代表着先进生产力的发展方向(并且就像煤炭行业至今仍然是采矿和机械制造业最先进技术的集中展示平台一样),但是悲哀的是,他们自身却不是先进生产力。

浅谈Spring MVC 过时了吗?

科技创新fanta2 发表了文章 • 0 个评论 • 45 次浏览 • 2021-04-16 14:47 • 来自相关话题

正文如下:问题:Spring MVC 过时了吗?我看了一下这个问题的日志,这个问题是2018年9月提出来的。那么好,首先给出结论:Spring MVC没有过时,它仍然是当前主流的Java Web开发框架。但是,在这个时间点谈论这个问题就有点意思了。题主提出这个... ...查看全部

正文如下:

问题:Spring MVC 过时了吗?

我看了一下这个问题的日志,这个问题是2018年9月提出来的。

那么好,首先给出结论:Spring MVC没有过时,它仍然是当前主流的Java Web开发框架。但是,在这个时间点谈论这个问题就有点意思了。题主提出这个问题的时候,可能都没有意识到这个问题正处在Web开发思想变革的分水岭上。

首先,说一下答主这个问题描述中不准确的地方,后面再着重说说现在的分水岭。

现在jsp似乎已经渐渐淡出大家的视野。web开发朝着前后端分离的方向去了

这个没错。但是,

像spring mvc这样前后端耦合较大的框架是否过时了?

这个疑问就没有必要了。

Spring MVC前后端耦合不大啊。你完全可以使用@RestController。

@RestControlleris a specialized version of the controller. It includes the @Controller and @ResponseBody annotations and as a result, simplifies the controller implementation:

@RestController@RequestMapping(“books-rest”)public class SimpleBookRestController {           @GetMapping(“/{id}”, produces = “application/json”)     public Book getBook(@PathVariable int id) {         return findBookById(id);     }       private Book findBookById(int id) {         // …    } }

前后端分离,没有JSP或其他服务器端模板引擎,只有HTTP上传输的JSON交互,那么必然用@RestController。JSON是服务器端MVC框架的V,是前端MVC框架的M。

————–重点开始————-

下面说一下为什么现在这个问题比较有意思了。

因为从Spring 5开始,大量引入了Reactive概念,也就是响应式思想!!!

所以,Spring 4及以前版本长期存在的Spring MVC有了一个并列同时存在的新的编程模型,Spring WebFlux。

上图,左侧是新的Spring WebFlux,可以看出一切都是Reactive的。右侧是我们熟悉的Spring MVC,是基于Servlet API的。

这个问题下的其他回答,竟然还在问:

那你是觉得哪个框架替代了Spring MVC?

你能找出其他框架来代替它吗?如果没有,那就没有过时

你们最近半年访问过Spring 官网首页吗?

特别是2018的Spring One大会,大家注意到了吗?看一下所有的话题(session),多少题目里都包含了Reactive:

所以,如果Spring认定了Reactive是趋势的话,传统的Spring MVC应该是处于Deprecated状态。上图中两种模型可能会长期并存,但是Spring 6以后就不好说了~

在今年的Spring One大会上,Spring提出了一整套Reactive技术,Spring 自己称作Reactive Revolution:

还有更多的Reactive思想涌现出来了,大家要保持关注。

不仅仅是服务器端,前端的Reactive也很活跃,例如Rxjs。

正如Spring自己定义的那样,现在是一场Reactive Revolution,这场思想革命波及Web开发的全栈,数据库=>服务器=>前端。

所以,此时想一下Spring MVC是否过时是个很有意思的问题。它仍是最主流最成熟的Java服务器端MVC框架,但它并不代表Web进化的方向。

评论区有人提到Vert.x。到目前Vert.x也只是个tool-kit,不适一整套框架。现在技术讲求的是生态环境,Spring现在基本上是占有生态优势,有Spring MVC的普及率。不管Spring MVC还是Web Flux,都能融入这个生态,Spring Boot都会给予先天的支持。

回复@无忧

编程首先思想活动,然后才是敲代码。学习编程的语言、框架等等,首先是思想跟上。比如前端用惯了JQuery的人,直接操作DOM,让他们学习Angular、VUE这总双向绑定,肯定也会觉得反直觉。但是说到底,思想在进步,落后的思想就会觉得先进思想反直觉。民国时期,多少人看到女人穿泳衣游泳也觉得反直觉,但是现在都是正常的。

生态也不是一天建成的,如果是个小团队提出的框架,我可能觉得会凉。但是以Spring多少年在Web开发上的积淀,然后能够自我革新提出Webflux,并且打算建立一整套Reacitve生态,我觉得成为主流还是很有可能的。还是拿前端的例子来说,为啥大家十年如一日JQuery用的好好的,然后接受Angularjs的双向绑定,因为首先是Google提出来的,它自己内部就有大量应用。为啥Angularjs用的好好的,突然又开始用React的Virtual DOM?因为首先是Facebook提出来的,它自己有成功的应用。

转载于公众号“程序猿DD”


作为程序员的你,这些一直接触的词都念对了吗?

科技创新小小鸟a 发表了文章 • 0 个评论 • 41 次浏览 • 2021-04-16 14:47 • 来自相关话题

很多时候,大家可能都觉得程序员英文一定很好。因为我们每天都对着满屏幕的英文,噼里啪啦一整天。讨论个需求,还是不是冒几个单词,产品MM和运营JJ们,心理几万头曹尼玛奔过:能不能讲人话!很多时候,我们自信满满的说出一个又一个高大上的操作名、技术名,看似装逼成功!但... ...查看全部

很多时候,大家可能都觉得程序员英文一定很好。因为我们每天都对着满屏幕的英文,噼里啪啦一整天。讨论个需求,还是不是冒几个单词,产品MM和运营JJ们,心理几万头曹尼玛奔过:能不能讲人话!

很多时候,我们自信满满的说出一个又一个高大上的操作名、技术名,看似装逼成功!但是我们都说对了吗?

下面,我们一起来重现一下这些场景,看看你都对了几个?

第一轮

单词一:Archive

Archive:档案、归档。常见于一些管理类需求或是运维相关日常。

正确发音:

  • 英:[ˈɑːkaɪv]

  • 美:[ˈɑːrkaɪv]

单词二:Digest

Digest:字面意思为摘要、汇编。常见于一些数字证书、认证算法相关的内容中。比如:HTTP的认证方式中有一种就叫Digest认证,是Basic认证的升级版。

正确发音:

  • 英:[daɪˈdʒest , ˈdaɪdʒest]

  • 美:[daɪˈdʒest , ˈdaɪdʒest]

第二轮

单词三:Adobe

Adobe:一家专注于图形设计、影像编辑与网络开发的著名软件公司。PhotoShop、Illustrator、Dreamweaver等设计类著名软件均为它们开发。如果您对设计师MM感兴趣?那么千万别再念错了!

正确发音:

  • 英:[əˈdəʊbi]

  • 美:[əˈdoʊbi]


单词四:Cache

Cache:缓存。不论在讨论硬件领域还是软件领域,前端还是后端技术时候,当碰到性能相关难题的时候,经常出现的一个词。你念对了吗?

正确发音:

  • 英:[kæʃ]

  • 美:[kæʃ]

第三轮

单词五:Apache

Apache:一款应用服务的名称,也是Java领域一个重要开源基金会的名称。近几年有好几个国内开源项目也都加入了Apache基金会,比如:我们所熟知的Dubbo、Skywalking!

正确发音:

  • 英:[əˈpætʃi] 

  • 美:[əˈpætʃi]

单词六:Suite

Suite:套件。比较常见于测试小组中,比如:Test Suite,意为测试套件、测试集合,代表已一组Test Case(测试用例)。

正确发音:

  • 英:[ˈɑːkaɪv]

  • 美:[ˈɑːrkaɪv]

转载于公众号“程序猿DD”


融云如何把图片消息的图片上传到自己的文件服务器

IM即时通讯大神庵 发表了文章 • 0 个评论 • 583 次浏览 • 2020-12-02 16:16 • 来自相关话题

我们使用融云开发的项目, 但我们有一个需求是, 把图片不要上传到融云的服务器, 而是自己的服务器.于是就咨询了一下技术支持.被告知有一个接口方法完全可以满足我们的需求.       &nbs... ...查看全部

我们使用融云开发的项目, 但我们有一个需求是, 把图片不要上传到融云的服务器, 而是自己的服务器.于是就咨询了一下技术支持.

微信截图_20201202160709.png

被告知有一个接口方法完全可以满足我们的需求.

             ImageMessage imageMessage = ImageMessage.obtain(Uri.parse(FILEPATH), Uri.parse(FILEPATH));
        configSendMessage(imageMessage);
        Message message = Message.obtain(mTargetId,mConversationType,imageMessage);
        RongIM.getInstance().sendImageMessage(message, "pushcontent", "pushdata",
                new RongIMClient.SendImageMessageWithUploadListenerCallback() {
                    @Override
                    public void onAttached(Message message, RongIMClient.UploadImageStatusListener watcher) {
                            // 这里是自己上传图片的逻辑, 图片的路径可以通过 message 中进行获取. 
                            //watcher 这个参数主要是用于把自己的上传状态同步给 sdk. 这样我们就可以使用 sdk 内部的默认逻辑, 包括界面.
                    }
                    @Override
                    public void onError(Message message, RongIMClient.ErrorCode code) {
                    }
                    @Override
                    public void onSuccess(Message message) {
                    }
                    @Override
                    public void onProgress(Message message, int progress) {
                    }
                });

这样就可以继续使用 IMkit 的界面以及其他逻辑, 只是在 onAttached 中编写我们的上传逻辑并使用 watcher 上传的进度、成功或失败状态同步给 sdk 即可.


融云 IMkit 拦截或监听所有发送消息

IM即时通讯大神庵 发表了文章 • 0 个评论 • 554 次浏览 • 2020-12-02 16:16 • 来自相关话题

最近集成融云 IMkit 的 SDK, 有一个需求是要监听所有发出去的消息, 根据消息类型拦截或者进行修改.在官方文档上着了一遍, 都没有找到, 偶然在看 API 文档的时候看见了一个监听然后做了尝试, 是可以满足需求的, 所以再次记录一下.具体的方法是 Ro... ...查看全部

微信截图_20201202160910.png

最近集成融云 IMkit 的 SDK, 有一个需求是要监听所有发出去的消息, 根据消息类型拦截或者进行修改.

在官方文档上着了一遍, 都没有找到, 偶然在看 API 文档的时候看见了一个监听然后做了尝试, 是可以满足需求的, 所以再次记录一下.

具体的方法是 RongIM 类下的 setSendMessageListener 方法.

代码如下.

 /**
     * 设置发送消息的监听。
     *
     * @param listener 发送消息的监听。
     */
    RongIM.setSendMessageListener(new OnSendMessageListener() {
           @Override
         public Message onSend(Message message) {
                 // 发送消息之前会走此方法. message 为要发送的消息,
                 // 如果返回 null 的话, 就不会发送此消息了.
                 return message;
         }
         @Override
        public boolean onSent(Message message, SentMessageErrorCode sentMessageErrorCode) {
                 发送成功之后会走方法. 返回 true , 就会走 SDK 的后续逻辑. 返回 false 就拦截了.         return true;
             }
    }).


融云清空历史消息 Android 端

IM即时通讯大神庵 发表了文章 • 0 个评论 • 598 次浏览 • 2020-12-02 16:16 • 来自相关话题

融云清空历史消息 Android 端先调用获取历史消息。/** * 根据会话类型的目标 Id,回调方式获取N条历史消息记录。 * * @param conversationType 会话类型。不支持传入&nbs... ...查看全部

融云清空历史消息 Android 端

微信截图_20201202161404.png

  1. 先调用获取历史消息。

/**
* 根据会话类型的目标 Id,回调方式获取N条历史消息记录。
*
* @param conversationType 会话类型。不支持传入 ConversationType.CHATROOM。
* @param targetId         目标 Id。根据不同的 conversationType,可能是用户 Id、讨论组 Id、群组 Id。
* @param oldestMessageId  最后一条消息的 Id,获取此消息之前的 count 条消息,没有消息第一次调用应设置为:-1。
* @param count            要获取的消息数量。
* @param callback         获取历史消息记录的回调,按照时间顺序从新到旧排列。
*/
public void getHistoryMessages(Conversation.ConversationType conversationType, String targetId, int oldestMessageId, int count, RongIMClient.ResultCallback<List<Message>> callback) {
RongIMClient.getInstance().getHistoryMessages(conversationType, targetId, oldestMessageId, count, callback);
}
  1. 再调用删除的接口。

/**
* 删除指定的一条或者一组消息,回调方式获取是否删除成功。
*
* @param messageIds 要删除的消息 Id 数组。
* @param callback   是否删除成功的回调。
*/
public void deleteMessages(final int[] messageIds, final RongIMClient.ResultCallback<Boolean> callback) {
RongIMClient.getInstance().deleteMessages(messageIds, new RongIMClient.ResultCallback<Boolean>() {
@Override
public void onSuccess(Boolean bool) {
if (bool)
RongContext.getInstance().getEventBus().post(new Event.MessageDeleteEvent(messageIds));
if (callback != null)
callback.onSuccess(bool);
}
@Override
public void onError(RongIMClient.ErrorCode e) {
if (callback != null)
callback.onError(e);
}
});
}

清除远端消息调接口

  1. cleanRemote 传 true ,时间戳传入当前的时间戳。

/**

  • 删除指定时间戳之前的消息,可选择是否同时删除服务器端消息

  • 此方法从服务器端清除历史消息,但是必须先开通历史消息云存储功能。

  • 根据会话类型和 TargetId 清除某一会话指定时间戳之前的本地数据库消息(服务端历史消息),

  • 清除成功后只能从本地数据库(服务端)获取到该时间戳之后的历史消息。

*
* @param conversationType 会话类型。
* @param targetId         会话目标ID。
* @param recordTime       清除消息截止时间戳,【0 ~ 当前时间的 Unix 时间戳】。
* @param cleanRemote      是否删除服务器端消息
* @param callback         清除消息的回调。
*/
public void cleanHistoryMessages
  1. 如果界面没有刷新,重新进入看下是否全部删除了。

您先试下是否可以删除,如果可以删除,但是界面没有刷新刷新的话,您可以调用 ConversationFragment 的

getMessageAdapter
方法,然后

mListAdapter.removeAll();

mListAdapter.notifyDataSetChanged();
试下。


唠一唠融云的消息扩展功能

IM即时通讯大神庵 发表了文章 • 0 个评论 • 598 次浏览 • 2020-12-02 16:16 • 来自相关话题

在使用融云 SDK 的过程中,由于定制化程度过高,其中有一项业务的实现是需要实现“红包”功能,但是实现的流程比较复杂:自定义红包消息 MoneyMessage ,然后 A 用户发送给B 用户,B 用户在点击之后,同样发送一个自定义通知消息给 A ,用来修改A ... ...查看全部

微信截图_20201202161542.png

在使用融云 SDK 的过程中,由于定制化程度过高,其中有一项业务的实现是需要实现“红包”功能,但是实现的流程比较复杂:

  • 自定义红包消息 MoneyMessage ,然后 A 用户发送给B 用户,B 用户在点击之后,同样发送一个自定义通知消息给 A ,用来修改A 用户的界面。

上述流程看上去比较简单,但是实现起来就会比较复杂,并且并不灵活,于是跟融云技术反馈此问题之后,在从 4.0.3 版本开始支持单条消息扩展信息设置功能,用 消息扩展功能实现就会无比简单。

消息扩展功能的本质是在Message 类中添加了扩展功能;

 /**
     * 设置是否可以包含扩展信息
     *
     * @param canIncludeExpansion 是否可以包含扩展信息
     */
   public void setCanIncludeExpansion(boolean canIncludeExpansion);
  /**
  * 消息扩展信息列表
  *
 * @return 消息扩展信息列表
 */
public Map<String, String> getExpansion();
 /**
* 设置消息扩展信息列表
* 扩展信息只支持单聊和群组,其它会话类型不能设置扩展信息。*
* @param expansion 消息扩展信息列表
*/
 public void setExpansion(HashMap<String, String> expansion);

可以调用 RongIMClient.getInstance().updateMessageExpansion(); 来设置消息扩展属性;
可以调用 RongIMClient.getInstance().removeMessageExpansion();来删除消息扩展属性;
当然监听消息属性可以设置:

   RongIMClient.getInstance().setMessageExpansionListener(new RongIMClient.MessageExpansionListener() {
        @Override
        public void onMessageExpansionUpdate(Map<String, String> expansion, Message message) {
        }
        @Override
        public void onMessageExpansionRemove(List<String> keyArray, Message message) {
        }
    });

来实时监听消息属性的变化,这样可以动态实现红包点击接受的功能,或者礼物场景的实现

融云即时通讯SDK集成 — 定制UI(二) ——添加自定义表情库

IM即时通讯徐凤年 发表了文章 • 0 个评论 • 564 次浏览 • 2020-12-02 16:03 • 来自相关话题

背景:最近公司新上的app要加上即时通讯的功能, 自己快速实现一个当然是不可能的了(项目deadline也顶不住哇).就从各家成熟的SDK厂商选来选去的, 各有各的好也各有各的不足.最后点兵点将,选了融云家的SDK(老板说了算hhhh).他家的官网和文档地址:... ...查看全部

背景:

最近公司新上的app要加上即时通讯的功能, 自己快速实现一个当然是不可能的了(项目deadline也顶不住哇).就从各家成熟的SDK厂商选来选去的, 各有各的好也各有各的不足.最后点兵点将,选了融云家的SDK(老板说了算hhhh).
他家的官网和文档地址:
官网:https://www.rongcloud.cn/
文档:https://docs.rongcloud.cn/v4
这个任务当然还是落在我的头上. 我是使用的他们家的带UI的sdk,(他们家有带UI和不带UI的两种sdk, 不带UI的sdk就是只有即时通讯能力, 所有的UI都需要开发者自定实现, 带UI的sdk封装了一些基本的界面,例如会话列表, 和别人聊天的会话界面.)当然这些已经集成了UI的sdk并不能完全满足一个产品的需求, 所以这篇文章跟大家讲下如何添加一套自定义的表情包.

效果如下哈:

QQ20201112-0.jpg

虽然这里有点难看了哈哈, 不过是为了给大家展示方法嘛, 就不管那么多了. 可以看到底下除了默认的emoji的表情包, 还多了一个tab, 我是从QQ表情搞了一套, 直接就加在这里了. 一个可爱的小猪猪🐷哈哈哈.

添加步骤

需要改动的有这么几个类:

AndroidEmoji: 控制emoji图标资源, 编码, 以及相应展示的类
RongExtension: 会话界面除去聊天气泡与title bar的整个下方输入区域
IEmoticonTab: 表情tab
DefaultExtensionModule: 表情tab的上层控件.

对于AndroidEmoji这个类, 可以直接照抄, 把资源文件替换成自己准备好的图标, 以及编码/描述

public class ConversationListAdapter extends BaseAdapter<UIConversation> {
    private final static String TAG = "ConversationListAdapter";
    LayoutInflater mInflater;
    Context mContext;
    @Override
    public long getItemId(int position) {
        UIConversation conversation = getItem(position);
        if (conversation == null)
            return 0;
        return conversation.hashCode();
    }
    protected class ViewHolder {
        public View layout;
        public View leftImageLayout;
        public View rightImageLayout;
        public View leftUnReadView;
        public View rightUnReadView;
        public AsyncImageView leftImageView;
        public TextView unReadMsgCount;
        public ImageView unReadMsgCountIcon;
        public AsyncImageView rightImageView;
        public TextView unReadMsgCountRight;
        public ImageView unReadMsgCountRightIcon;
        public ProviderContainerView contentView;
    }
    public ConversationListAdapter(Context context) {
        super();
        mContext = context;
        mInflater = LayoutInflater.from(mContext);
    }
    public int findGatheredItem(Conversation.ConversationType type) {
        int index = getCount();
        int position = -1;
        while ((index-- > 0)) {
            UIConversation uiConversation = getItem(index);
            if (uiConversation.getConversationType().equals(type)) {
                position = index;
                break;
            }
        }
        return position;
    }
    public int findPosition(Conversation.ConversationType type, String targetId) {
        int index = getCount();
        int position = -1;
        while (index-- > 0) {
            if (getItem(index).getConversationType().equals(type)
                    && getItem(index).getConversationTargetId().equals(targetId)) {
                position = index;
                break;
            }
        }
        return position;
    }
    @Override
    protected View newView(Context context, int position, ViewGroup group) {
        View result = mInflater.inflate(R.layout.rc_item_conversation, null);
        ViewHolder holder = new ViewHolder();
        holder.layout = findViewById(result, R.id.rc_item_conversation);
        holder.leftImageLayout = findViewById(result, R.id.rc_item1);
        holder.rightImageLayout = findViewById(result, R.id.rc_item2);
        holder.leftUnReadView = findViewById(result, R.id.rc_unread_view_left);
        holder.rightUnReadView = findViewById(result, R.id.rc_unread_view_right);
        holder.leftImageView = findViewById(result, R.id.rc_left);
        holder.rightImageView = findViewById(result, R.id.rc_right);
        holder.contentView = findViewById(result, R.id.rc_content);
        holder.unReadMsgCount = findViewById(result, R.id.rc_unread_message);
        holder.unReadMsgCountRight = findViewById(result, R.id.rc_unread_message_right);
        holder.unReadMsgCountIcon = findViewById(result, R.id.rc_unread_message_icon);
        holder.unReadMsgCountRightIcon = findViewById(result, R.id.rc_unread_message_icon_right);
        result.setTag(holder);
        return result;
    }
    @Override
    protected void bindView(View v, int position, final UIConversation data) {
        ViewHolder holder = (ViewHolder) v.getTag();
        if (data == null) {
            return;
        }
        /*通过会话类型,获得对应的会话provider.ex: PrivateConversationProvider*/
        IContainerItemProvider provider = RongContext.getInstance().getConversationTemplate(data.getConversationType().getName());
        if (provider == null) {
            RLog.e(TAG, "provider is null");
            return;
        }
        View view = holder.contentView.inflate(provider);
        provider.bindView(view, position, data);
        //设置背景色
        if (data.isTop())
            holder.layout.setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.rc_item_top_list_selector));
        else
            holder.layout.setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.rc_item_list_selector));
        ConversationProviderTag tag = RongContext.getInstance().getConversationProviderTag(data.getConversationType().getName());
        int defaultId;
        if (data.getConversationType().equals(Conversation.ConversationType.GROUP)) {
            defaultId = R.drawable.rc_default_group_portrait;
        } else if (data.getConversationType().equals(Conversation.ConversationType.DISCUSSION)) {
            defaultId = R.drawable.rc_default_discussion_portrait;
        } else {
            defaultId = R.drawable.rc_default_portrait;
        }
        // 1:图像靠左显示。2:图像靠右显示。3:不显示图像。
        if (tag.portraitPosition() == 1) {
            holder.leftImageLayout.setVisibility(View.VISIBLE);
            holder.leftImageLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnPortraitItemClick != null)
                        mOnPortraitItemClick.onPortraitItemClick(v, data);
                }
            });
            holder.leftImageLayout.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    if (mOnPortraitItemClick != null)
                        mOnPortraitItemClick.onPortraitItemLongClick(v, data);
                    return true;
                }
            });
            if (data.getConversationGatherState()) {
                holder.leftImageView.setAvatar(null, defaultId);
            } else {
                if (data.getIconUrl() != null) {
                    holder.leftImageView.setAvatar(data.getIconUrl().toString(), defaultId);
                } else {
                    holder.leftImageView.setAvatar(null, defaultId);
                }
            }
            if (data.getUnReadMessageCount() > 0) {
                holder.unReadMsgCountIcon.setVisibility(View.VISIBLE);
                setUnReadViewLayoutParams(holder.leftUnReadView, data.getUnReadType());
                if (data.getUnReadType().equals(UIConversation.UnreadRemindType.REMIND_WITH_COUNTING)) {
                    if (data.getUnReadMessageCount() > 99) {
                        holder.unReadMsgCount.setText(mContext.getResources().getString(R.string.rc_message_unread_count));
                    } else {
                        holder.unReadMsgCount.setText(Integer.toString(data.getUnReadMessageCount()));
                    }
                    holder.unReadMsgCount.setVisibility(View.VISIBLE);
                    holder.unReadMsgCountIcon.setImageResource(R.drawable.rc_unread_count_bg);
                } else {
                    holder.unReadMsgCount.setVisibility(View.GONE);
                    holder.unReadMsgCountIcon.setImageResource(R.drawable.rc_unread_remind_list_count);
                }
            } else {
                holder.unReadMsgCountIcon.setVisibility(View.GONE);
                holder.unReadMsgCount.setVisibility(View.GONE);
            }
            holder.rightImageLayout.setVisibility(View.GONE);
        } else if (tag.portraitPosition() == 2) {
            holder.rightImageLayout.setVisibility(View.VISIBLE);
            holder.rightImageLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnPortraitItemClick != null)
                        mOnPortraitItemClick.onPortraitItemClick(v, data);
                }
            });
            holder.rightImageLayout.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    if (mOnPortraitItemClick != null)
                        mOnPortraitItemClick.onPortraitItemLongClick(v, data);
                    return true;
                }
            });
            if (data.getConversationGatherState()) {
                holder.rightImageView.setAvatar(null, defaultId);
            } else {
                if (data.getIconUrl() != null) {
                    holder.rightImageView.setAvatar(data.getIconUrl().toString(), defaultId);
                } else {
                    holder.rightImageView.setAvatar(null, defaultId);
                }
            }
            if (data.getUnReadMessageCount() > 0) {
                holder.unReadMsgCountRightIcon.setVisibility(View.VISIBLE);
                setUnReadViewLayoutParams(holder.rightUnReadView, data.getUnReadType());
                if (data.getUnReadType().equals(UIConversation.UnreadRemindType.REMIND_WITH_COUNTING)) {
                    holder.unReadMsgCount.setVisibility(View.VISIBLE);
                    if (data.getUnReadMessageCount() > 99) {
                        holder.unReadMsgCountRight.setText(mContext.getResources().getString(R.string.rc_message_unread_count));
                    } else {
                        holder.unReadMsgCountRight.setText(Integer.toString(data.getUnReadMessageCount()));
                    }
                    holder.unReadMsgCountRightIcon.setImageResource(R.drawable.rc_unread_count_bg);
                } else {
                    holder.unReadMsgCount.setVisibility(View.GONE);
                    holder.unReadMsgCountRightIcon.setImageResource(R.drawable.rc_unread_remind_without_count);
                }
            } else {
                holder.unReadMsgCountIcon.setVisibility(View.GONE);
                holder.unReadMsgCount.setVisibility(View.GONE);
            }
            holder.leftImageLayout.setVisibility(View.GONE);
        } else if (tag.portraitPosition() == 3) {
            holder.rightImageLayout.setVisibility(View.GONE);
            holder.leftImageLayout.setVisibility(View.GONE);
        } else {
            throw new IllegalArgumentException("the portrait position is wrong!");
        }
        MessageContent content = data.getMessageContent();
        if (content != null && content.isDestruct()) {
            RongIMClient.getInstance().getMessage(data.getLatestMessageId(), new RongIMClient.ResultCallback<Message>() {
                @Override
                public void onSuccess(Message message) {
                    if (message == null) {
                        EventBus.getDefault().post(new Event.MessageDeleteEvent(data.getLatestMessageId()));
                    }
                }
                @Override
                public void onError(RongIMClient.ErrorCode e) {
                }
            });
        }
    }
    protected void setUnReadViewLayoutParams(View view, UIConversation.UnreadRemindType type) {
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
        Context context = view.getContext();
        if (type == UIConversation.UnreadRemindType.REMIND_WITH_COUNTING) {
            params.width = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_18);
            params.height = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_18);
            params.leftMargin = (int) mContext.getResources().getDimension(R.dimen.rc_dimen_size_44);
            params.topMargin = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_5);
        } else {
            params.width = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_9);
            params.height = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_9);
            params.leftMargin = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_50);
            params.topMargin = (int) context.getResources().getDimension(R.dimen.rc_dimen_size_7);
        }
        view.setLayoutParams(params);
    }
    private OnPortraitItemClick mOnPortraitItemClick;
    public interface OnPortraitItemClick {
        void onPortraitItemClick(View v, UIConversation data);
        boolean onPortraitItemLongClick(View v, UIConversation data);
    }
    public void setOnPortraitItemClick(OnPortraitItemClick onPortraitItemClick) {
        this.mOnPortraitItemClick = onPortraitItemClick;
    }
}

集成DefaultExtensionModule, 实现MyExtensionModule, 重写getEmoticonTabs()方法, 为每个图标设置监听.

@Override
    public List<IEmoticonTab> getEmoticonTabs() {
        List<IEmoticonTab> emoticonTabs =  super.getEmoticonTabs();
        MyEmoticonTab myEmoticonTab =new MyEmoticonTab();
        myEmoticonTab.setOnItemClickListener(new IEmojiItemClickListener() {
            @Override
            public void onEmojiClick(String emoji) {
                EditText editText = MyExtensionModule.this.mEditText;
                if (editText != null) {
                    int start = editText.getSelectionStart();
                    editText.getText().insert(start, emoji);
                }
            }
            @Override
            public void onDeleteClick() {
                EditText editText = MyExtensionModule.this.mEditText;
                if (editText != null) {
                    editText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
                }
            }
        });
        emoticonTabs.add(myEmoticonTab);
        return emoticonTabs;
    }

继承RongExtension, 实现MyRongExtension, 然后获取到editText, 为其设置监听, 代码如下:

public class MyRongExtension extends RongExtension {
    EditText mEditText;
    public MyRongExtension(Context context) {
        super(context);
        tryAddTextChangedAction();
    }
    public MyRongExtension(Context context, AttributeSet attrs) {
        super(context, attrs);
        tryAddTextChangedAction();
    }
    private void tryAddTextChangedAction() {
        mEditText = getInputEditText();
        TextWatcher textWatcher = new TextWatcher() {
            private int start;
            private int count;
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                this.start = start;
                this.count = count;
            }
            @Override
            public void afterTextChanged(Editable s) {
                // 这块的检验规则是纯emoji的, 加其他表情的话直接给他去掉, 或者自己写规则。
//                if (QQEmoji.isQQEmoji(s.subSequence(start, start + count).toString())) {
                    mEditText.removeTextChangedListener(this);
                    String resultStr = QQEmoji.replaceEmojiWithText(s.toString());
                    mEditText.setText(QQEmoji.ensure(resultStr), TextView.BufferType.SPANNABLE);
                    mEditText.setSelection(mEditText.getText().length());
                    mEditText.addTextChangedListener(this);
//                }
            }
        };
        mEditText.addTextChangedListener(textWatcher);
    }
}

这样一来, 就大功告成啦. 添加好了一套属于自己的表情包!

融云即时通讯SDK集成 — 华为推送的点击跳转处理

IM即时通讯徐凤年 发表了文章 • 0 个评论 • 238 次浏览 • 2020-12-02 15:58 • 来自相关话题

1.背景:最近公司新上的app要加上即时通讯的功能, 自己快速实现一个当然是不可能的了(项目deadline也顶不住哇).就从各家成熟的SDK厂商选来选去的, 各有各的好也各有各的不足.最后点兵点将,选了融云家的SDK(老板说了算hhhh).他家的官网和文档地... ...查看全部

1.背景:

最近公司新上的app要加上即时通讯的功能, 自己快速实现一个当然是不可能的了(项目deadline也顶不住哇).就从各家成熟的SDK厂商选来选去的, 各有各的好也各有各的不足.最后点兵点将,选了融云家的SDK(老板说了算hhhh).
他家的官网和文档地址:
官网:https://www.rongcloud.cn/
文档:https://docs.rongcloud.cn/v4
这个任务当然还是落在我的头上. 基础的IM聊天, 群组聊天等功能集成在另一篇博客中已经讲过, 这里就先不说了. 之前的一篇文章已经讲过, 这篇文章重点讲下华为推送过来的通知栏点击事件, 这小小的一件事, 可耗费了不少的精力.

2. 融云家SDK接入厂商推送指南

这个他家讲的挺清楚了, 都近似手把手的教了, 那我也就不在这浪费键盘寿命了(偷个懒hhhhh).给他家官方文档往这儿一贴好了: https://docs.rongcloud.cn/v4/views/im/ui/guide/private/notify/push/mi.html. 大家注意一下他家华为厂商推送的文档分2.x和4.x哈, 对应的是他家旧版/新版SDK中接入的厂商的新/旧版本推送包.我这里之前是踩过坑的, 推荐大家还是用他家的4.x的sdk包集成, 里边集成的是华为新版本的推送包. 因为华为已经在逐渐弃用旧版本的推送包了, 所以不想以后麻烦再迭代的话, 还是直接上新版本比较好, 因为现在已经有接入旧版本包的app在某些低版本华为Rom上收不到推送了, 还是谨慎一点比较好.

3. 华为推送通知点击跳转自定义

这里我们所指的跳转是, 点击通知栏到达的华为推送通知后, 调起我们的app, 跳到相应的Activity的. 因为我们做的是即时通讯App, 所以点击别人发来的消息推送通知后, 当然是跳到和该用户聊天的会话页面, 但就是这样一个小业务, 实现起来还真有点麻烦. 所以这里也算是给大家踩踩坑啦.

首先是点击跳转的逻辑, 通过和融云技术支持联系以及查看他们sdk的代码, 得知他们的推送都是走了一个叫PushMessageReceiver的类, 开发者可以注册并继承该类, 重写onNotificationMessageClicked()方法, 显而易见这就是对通知消息的监听. 可这也是第一个坑, 华为因为平台的限制, 推送通知的点击事件根本不走这里. 准确的说是华为和Oppo都因为各自平台的限制, 不走这里. 所以当我兴致勃勃重写了这个方法准备一次通过的时候, 点击后直接走到了会话列表界面, 而非会话界面.

这是因为华为平台点击跳转是需要配一个intent, 在融云的后台, 如图所示:
QQ20201102-111109@2x.png

这里的intent即为通知栏点击跳转后的隐式启动相应activity的那个intent.

获取某Activity相应intent的代码, 可把intent给打到log中:

  1. Intent intent =newIntent(Intent.ACTION_VIEW,

  2.                Uri.parse("wonderfullpush://com.wonderfull.android.push/notification?action=your parameter"));

  3.        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

  4.        intent.setAction(Intent.ACTION_VIEW);

  5.        String intnetUri = intent.toUri(Intent.URI_INTENT_SCHEME);

  6.        Log.d("hwpush","intnetUri="+ intnetUri);

生成的intent大概是这样的格式:

  1. intent://com.wonderfull.android.push/notification?action=$action#Intent;scheme=wonderfullpush;action=android.intent.action.VIEW;launchFlags=0x10000000;end

不过这块还有坑, 还不能直接把装会话界面的activity的intent直接写在这里, 因为这个会话界面去的究竟是哪个对话者的界面, 相应userId的参数是传不到的. 在这里我尝试获取过intent里边的数据, 是空的.

和融云的技术支持团队确认后, 找到了解决方案. 只有intent走到入口类, 才能拿的到通知里携带的数据, 我app的闪屏页, 也就是SplashActivity, 在融云后台把自定义点击跳转intent配成SplashActivity的. 然后在这里把intent的数据拿到, 再一次调用融云的接口跳转到相应的会话界面就OK了.

等拿到这个intent的后, 又是来了一点点小麻烦. 根据融云的文档, 我在入口Activity(闪屏页, SplashActivity)这里接收到了intent, 从intent里边取相应的数据:

这个intent中给的数据包含了转义符:

{"rc":"{\"conversationType\":\"1\",\"targetId\":\"userid8\",\"sourceType\":\"0\",\"fromUserId\":\"userid8\",\"objectName\":\"RC:TxtMsg\",\"id\":\"BLCG-G8TC-U7E6-KV7P\",\"tId\":\"doctorid3\"}"}
String jsonStr = "{\"rc\":\"{\\\"conversationType\\\":\\\"1\\\",\\\"targetId\\\":\\\"userid8\\\",\\\"sourceType\\\":\\\"0\\\",\\\"fromUserId\\\":\\\"userid8\\\",\\\"objectName\\\":\\\"RC:TxtMsg\\\",\\\"id\\\":\\\"BLCG-G8TC-U7E6-KV7P\\\",\\\"tId\\\":\\\"doctorid3\\\"}\"}";        String fixStr1 = jsonStr.replace("\\", "");        String fixStr2 = fixStr1.replace("\"rc\":\"", "\"rc\":" );        String result = fixStr2.replace("\"}\"", "\"}");        Log.d(TAG, "result jsonStr: "+ result);        JSONObject jsonObject;        try {            jsonObject = new JSONObject(result);            String options = jsonObject.getString("rc");            JsonObject object = (JsonObject) new JsonParser().parse(options);            String targetId = object.getAsJsonObject().get("targetId").getAsString();            Log.d(TAG, "analyse json targetId: " + targetId);        } catch (JSONException e) {            e.printStackTrace();        }

我选择了自行处理字符串, 拿到了相应的targetId, 从我的闪屏页跳转到相应的会话界面去. 这样需求就搞定了.


融云即时通讯SDK集成 — 定制UI(一) ——会话界面小改动

IM即时通讯徐凤年 发表了文章 • 0 个评论 • 586 次浏览 • 2020-12-02 15:58 • 来自相关话题

背景:最近公司新上的app要加上即时通讯的功能, 自己快速实现一个当然是不可能的了(项目deadline也顶不住哇).就从各家成熟的SDK厂商选来选去的, 各有各的好也各有各的不足.最后点兵点将,选了融云家的SDK(老板说了算hhhh).他家的官网和文档地址:... ...查看全部

背景:

最近公司新上的app要加上即时通讯的功能, 自己快速实现一个当然是不可能的了(项目deadline也顶不住哇).就从各家成熟的SDK厂商选来选去的, 各有各的好也各有各的不足.最后点兵点将,选了融云家的SDK(老板说了算hhhh).
他家的官网和文档地址:
官网:https://www.rongcloud.cn/
文档:https://docs.rongcloud.cn/v4
这个任务当然还是落在我的头上. 我是使用的他们家的带UI的sdk,(他们家有带UI和不带UI的两种sdk, 不带UI的sdk就是只有即时通讯能力, 所有的UI都需要开发者自定实现, 带UI的sdk封装了一些基本的界面,例如会话列表, 和别人聊天的会话界面.)当然这些已经集成了UI的sdk并不能完全满足一个产品的需求, 所以这篇文章主要跟大家讲下如何对他们家的UI进行简单的自定义.

融云SDK接入会话列表/会话界面

大家集成的话可以直接按照他们家的快速集成的步骤走, 包含了集成会话列表以及会话界面. 这里是链接: 快速集成SDK (https://docs.rongcloud.cn/v4/views/im/noui/guide/quick/include/android.html)

接入之后, 可以按照合适的逻辑跳转入这两个基本的界面, 如图所示:
会话列表:
QQ20201102-165916@2x.png会话界面
QQ20201102-165944@2x.png

可以看到我们的app中现在拥有了默认会话列表和会话界面UI, 可以使用基本的功能了. 但是这些基本的UI虽说不上难看, 但是也够不上精美. 所以UI这块还是需要我们自行来做一些定制的.

为了给大家演示, 我这里改的比较夸张了一点, 十分丑陋, 但直观哈哈哈.

3F7310C0-9826-4505-9CE8-56B1EE4427EA.png

如图我直接更改了两边发送者&接收者的字体颜色,字体大小,字体样式. 也更改了双方的聊天气泡.

修改普通文字消息类型的消息, 直接继承了TextMessageItemProvider. 把父类里边所有的代码都复制进来, 然后在bindView()的时候做修改

可以看到我把样式随便改了一下. 两个方向的气泡都改成了箭头左向的.

@Override
    public void bindView(final View v, int position, TextMessage content, final UIMessage data) {
        ViewHolder holder = (ViewHolder) v.getTag();
        holder.receiverFire.setTag(data.getUId());
        if (data.getMessageDirection() == Message.MessageDirection.SEND) {
            holder.message.setBackgroundResource(R.drawable.rc_ic_bubble_right);
        } else {
            holder.message.setBackgroundResource(R.drawable.rc_ic_bubble_left);
        }
        if (content.isDestruct()) {
            bindFireView(v, position, content, data);
        } else {
            holder.sendFire.setVisibility(View.GONE);
            holder.receiverFire.setVisibility(View.GONE);
            holder.unRead.setVisibility(View.GONE);
            holder.message.setVisibility(View.VISIBLE);
            final AutoLinkTextView textView = holder.message;
            processTextView(v, position, content, data, textView);
        }
    }

做完改动, 还需要给这个类添加这样的注解才能绑定TextMessage的渲染:

@ProviderTag(
        messageContent = TextMessage.class,
        showReadState = true
)
    public class MyTextMessageItemProvider extends TextMessageItemProvider

然后记得在init 我们SDK之后, 注册一下这个Provider.

 RongIM.init(this, APP_KEY);
    RongIM.registerMessageTemplate(new MyTextMessageItemProvider());

这样所有收到的类型为TextMessage的消息, 都会按照我这里定义的TextMessageItemProvider来做展示了. 其他类型的消息也是一样的, 语音, 文件, 位置消息. 只要想改UI, 本质上都是集成相应的MessageItemProvider, 然后重写bindView()方法.


融云即时通讯SDK集成 — 定制UI(三) ——兼容Android Q

IM即时通讯徐凤年 发表了文章 • 0 个评论 • 568 次浏览 • 2020-12-02 15:58 • 来自相关话题

背景:最近公司新上的app要加上即时通讯的功能, 自己快速实现一个当然是不可能的了(项目deadline也顶不住哇).就从各家成熟的SDK厂商选来选去的, 各有各的好也各有各的不足.最后点兵点将,选了融云家的SDK(老板说了算hhhh).他家的官网和文档地址:... ...查看全部

背景:

最近公司新上的app要加上即时通讯的功能, 自己快速实现一个当然是不可能的了(项目deadline也顶不住哇).就从各家成熟的SDK厂商选来选去的, 各有各的好也各有各的不足.最后点兵点将,选了融云家的SDK(老板说了算hhhh).
他家的官网和文档地址:
官网:https://www.rongcloud.cn/
文档:https://docs.rongcloud.cn/v4

微信截图_20201202155726.png

如何兼容Android Q

Android 10 适配
前言
为了让用户更好地控制自己的文件,并限制文件混乱的情况,Android 10(Q) 修改了 APP 访问外部存储中文件的方法。外部存储的新特性被称为 Scoped Storage。

Android 10(Q) 仍然使用 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE 作为面向用户的存储相关运行时权限,但现在即使获取了这些权限,访问外部存储也受到了限制。APP 需要这些运行时权限的情景发生了变化,且各种情况下外部存储对 APP 的可见性也发生了变化 在 Scoped Storage 新特性中,外部存储空间被分为两部分:

● 公共目录:Downloads、Documents、Pictures 、DCIM、Movies、Music、Ringtones 等

公共目录下的文件在 APP 卸载后,不会删除。

APP 可以通过 SAF(System Access Framework)、MediaStore 接口访问其中的文件。

● App-specific 目录

APP 卸载后,数据会清除。

APP 的私密目录,APP 访问自己的 App-specific 目录时无需任何权限。

融云关于 Android 10(Q)适配
之前 SDK 将媒体文件存储于 /sdcard/RongCloud/Media 中,所以在 android 10(Q) 系统上会有聊天无法使用的情况,新版本更新后,会将媒体消息存储于 :sdcard/Android/data/包名/files/ 中,以保证 sdk 功能的正常使用

用户需要做的适配工作
1.如果您是 kit 的用户,我们对融云基本消息类型进行了全面兼容,如果您自定义了媒体消息,建议您在点击自定义媒体消息时,对本地文件进行检查,如果本地文件流无法读取,调用 RongIM 的 downloadMediaMessage() 方法重新下载更新本地路径

示例代码

//1.判断小视频本地文件是否存在
if (sightMessage.getLocalPath() != null && !TextUtils.isEmpty(sightMessage.getLocalPath().toString())) {
            return FileUtils.isFileExistsWithUri(this, sightMessage.getLocalPath());
        } else {
            return false;
        }
//2.调用 downloadMediaMessage 下载文件刷新 ui
  RongIM.getInstance().downloadMediaMessage(mMessage, downloadMediaMessageCallback);

2.如果您是 lib 的用户,建议您在用户使用到媒体类型消息时,对消息体中的 localPath 进行判断检查,如果本地文件流无法正常访问,请调用 RongIMClient 的 downloadMediaMessage() 方法对媒体文件进行重新下载并更新本地路径,具体代买可参考以上代码进行具体调整

备注
文件存储路径变化

不开启 rc_q_storage_mode_enable 的各种文件保存路径
//使用sight模块录制小视频时
录制视频:sdcard/sdcard/RongCloud/Image/应用名/image/
下载音频 /sdcard/RongCloud/Media
下载视频 /sdcard/RongCloud/Media
下载文件 /sdcard/RongCloud/Media
下载 gif /sdcard/RongCloud/Media
自定义媒体文件 /sdcard/RongCloud/Media
开启 rc_q_storage_mode_enable 的各种文件保存路径
//使用sight模块录制小视频时
录制视频:sdcard/Android/data/包名/files/RongCloud/video/
下载音频:sdcard/Android/data/包名/files/RongCloud/audio/
下载视频:sdcard/Android/data/包名/files/RongCloud/video/
下载文件:sdcard/Android/data/包名/files/RongCloud/file/
下载 gif:sdcard/Android/data/包名/files/RongCloud/image/
自定义媒体文件 会根据媒体类型存储到以上目录中


万维网的诞生 | 当我们在浏览器输入网址并回车后,发生了什么?

IM即时通讯徐凤年 发表了文章 • 0 个评论 • 319 次浏览 • 2020-06-30 17:08 • 来自相关话题

编者按:1989年3月12日,欧洲粒子物理研究所软件顾问蒂姆&middot;李提交一个构建信息管理系统的计划&ldquo;Information Management: A Proposal&rdquo;,以便更好地管理实验室研究信息。... ...查看全部

编者按:1989年3月12日,欧洲粒子物理研究所软件顾问蒂姆&middot;李提交一个构建信息管理系统的计划&ldquo;Information Management: A Proposal&rdquo;,以便更好地管理实验室研究信息。该计划促使了万维网(WWW)诞生。1994年,中科院高能所架设了中国第一台WWW服务器,并推出第一个网站www.ihep.ac.cn,这项工程的亲历者许榕生研究员讲述了万维网(WWW)诞生的历史。

风靡世界的互联网环球信息技术World Wide Web(简称WWW)的发明源自上世纪八十年代。英国人蒂姆&middot;伯纳斯&middot;李(Tim Berners-Lee)于1989年成功地开发出世界上第一个Web服务器和第一个Web客户端软件,把互联网的应用推上了一个崭新的台阶,极大地促进了人类社会的信息化进程。因&ldquo;发明万维网、第一个浏览器和使万维网得以扩展的基本协议和算法&rdquo;而授予了蒂姆&middot;伯纳斯&middot;李图灵奖(2016年)。

互联网的雏形早在1960年代就诞生了,为什么没有迅速流传开来呢?其实,很重要的原因是早年联接到网络上需要经过一系列复杂的操作,并且不同的计算机具有不同的操作系统和不同的文件结构格式,使得跨平台的信息文件只能相互独立地划成孤岛。蒂姆曾经用一副非常形象的图画表明了他的创意(图1),即通过一种超文本方式,把分布在网络上的不同计算机内的信息有机地结合在一起,通过超文本传输协议(HTTP)从任意的Web服务器转到一台Web浏览器上进行无障碍的信息检索。这个叫Web的软件还能支持图文并茂的信息,甚至还允许发布音频和视频。这就使得后来的互联网远程教育及在线购物等等得以实现!此外,互联网的许多其它功能,如E-mail、Telnet、FTP、WAIS等内容也都可通过Web框架进行实现。

1990年12月25日,蒂姆和法国网络高手罗伯特&middot;卡里奥(Robert Cailliau)在西欧高能物理中心(CERN)一起成功地通过互联网展现了基于Web原理的HTTP代理与服务器的第一次通讯。短短的时间内,这项技术推广到了全世界。


图1 蒂姆&middot;伯纳斯&middot;李用这张图说明了WWW的创意,使原来不同计算机上的信息无法沟通,而现在可以用任何一台计算机对任何Web服务器上的信息库进行调用。


英国女皇伊丽莎白二世2004年向伯纳斯&middot;李颁发大英帝国爵级司令勋章。2009年4月,他获选为美国国家科学院外籍院士。2012年夏季奥林匹克运动会开幕典礼上,蒂姆获得了&ldquo;万维网发明者&rdquo;的美誉,他本人也参与了开幕典礼。

根据有关资料介绍,蒂姆&middot;伯纳斯&middot;李出生于英格兰伦敦西南部,他的父母都参加过世界上第一台商业计算机的建造。1973年,他中学毕业进入牛津大学王后学院深造,1976年从牛津大学物理系毕业后曾经供职于一些高科技公司,从事集成电路和系统设计的研究。1980年,一个偶然的机会,蒂姆来到瑞士的日内瓦,进入到CERN的一个实验室组里。该实验室组的首席是华裔物理学家、诺贝尔奖获得者丁肇中教授。

享誉世界的实验物理学家丁肇中教授在基本粒子研究方面取得一系列重大突破,独立发现了第四种夸克的束缚态,即J粒子,由此开拓了基本粒子研究的新领域。那段时期,丁教授在欧洲高能物理研究中心领导着L3的实验,该实验组首次邀请了由美国、前苏联、中国、欧洲等600名科学家共同参加大型国际合作研究。

在那里,年轻的蒂姆接受了一项极富挑战性的工作:为了使实验组里各国的高能物理学家能通过计算机网络及时沟通并传递信息,实验组委托他开发一个软件,以便让分布在各国实验组成员能够把最新的信息、数据、设计图资料等及时地提供给全体人员共享,随时随地犹如大家都在一起地方同步工作。早在牛津大学主修物理时蒂姆就不断地思索,是否可以找到一个"点",就好比人脑,能够透过神经传递、自主作出反应。以此为思路,蒂姆经过一段努力,终于编制成功了第一个高效局部存取浏览器"Enquire",并把它应用于数据共享浏览中。

1984年蒂姆作为正式成员重返欧洲核子物理实验室,他恢复了过去的工作,并正式写下了世界上第一个网页浏览器(World Wide Web)和第一个网页服务器(httpd)的软件源码。这时蒂姆把目标瞄向了建立一个全球范围的信息检索系统,以彻底打破信息存取的孤立行为。1989年3 月,蒂姆向CERN递交了一份立项建议书,建议采用超文本技术(Hypertext)首先把CERN内部的各个实验室连接起来,在系统建成后,可以扩展到全世界。这个激动人心的建议在CERN引起轩然大波,但开始没有被上司通过。

蒂姆并没有灰心,关键是他看到了突破口,是金子总会闪亮的!他花了2个月重新修改了建议书的措辞,最后终于得到了批准。于是蒂姆有了一笔经费,购买了一台NEXT计算机,并率领一批助手在上面开发系统。在1991年8月6日,蒂姆建立了第一个WWW网站(也是世界上第一个网站),网址是http://info.cern.ch/,在这个网站里还罗列出了各国跟进的WWW网站名单。这项利用互联网+超链接的闪亮原创就在CERN顺理成章地迅速推广开来。


蒂姆&middot;伯纳斯&middot;李

时值90年代初,中国建立了北京正负电子对撞机工程,为推动我国高能物理网络环境的进一步发展,我到了位于日内瓦的CERN考察,在访问期间就被安排在蒂姆原来的办公室内,很幸运地接触到这位WWW发明人。蒂姆在办公室门口贴了一张大黑蜘蛛趴在网上的图画,他给我解释说英文里Web也是网。他热情推荐我参加当年(1994年)4月10日召开的第一届国际WWW技术论坛大会,他做主题演讲,我亲眼看到会上会下群情振奋,所有人都感觉到一个重大的事件即将在世界上发生。那天他在屏幕上专门打出一张世界地图,用颜色标明已经推广了WWW技术的国家(当时主要集中在欧美各国),然后他刻意指着中国区域预言这里也快了。因为他知道我已经在组织策划国内着手启用WWW这项技术。

几天后,位于北京的高能物理所架设了中国第一台WWW服务器,推出了第一个网站www.ihep.ac.cn和英文网页,此刻在亚洲还没几个Web网站出现。

那年我也曾经邀请蒂姆到中国做报告,但他当时在世界各国的报告都已经安排满满的了,便派了他的助手到北京介绍WWW。差不多二十年后的2013年蒂姆才第一次得以访问了中国。

今天作为Web之父的蒂姆已经功成名就。但并不像大多数普通人都认为的那样,WWW的建立是通向致富的捷径。与那些依托互联网一夜暴富之士相比,蒂姆仍然坚守在学术研究岗位上,那种视富贵如浮云的胸襟,真正表现了一个献身科学的学者风度。回顾过去,我们看到伟大的全球互联网事业,正是由无数像蒂姆&middot;伯纳斯&middot;李这样的先驱们的无私耕耘才成长起来的。

在WWW诞生29周年之际,63岁的蒂姆发表了一封公开信,信中强调了目前互联网发展似乎正面临着一些威胁。蒂姆意识到了网络的无穷威力将给政府、企业和社会带来的剧烈改变。他预见这个发明一旦落入不适当的人手中,将成为世界的灾难。有人忙着打造一个接一个的社群网络、在线商业平台,很少会去设想他们可能带来什么后遗症。而蒂姆过去近三十年的时间里却都在努力保护互联网的纯洁,使自己的这项发明更好地造福人类,尽管他从未曾因为这个发明而直接获利。

互联网的安全问题日益显示出许多弱点,尤其过去几年里,脸书外泄超过了8000万用户个人资料,更多的网络运营商在想方设法收集个人隐私。

今年初,蒂姆出席了美国华盛顿的全球信息网基金会(World Wide Web Foundation)年度会议,这个基金会致力于保障数字环境中的人权。他认为这是一项迫切的任务,因为据他的估计,到今年下半年全球网络人口将达到四十亿。随着越来越多人在网络上分享他们的履历、政治倾向、DNA信息,网络将变得更加强大、更有价值,但同时也更加危险。

一开始,WWW技术确实是开放、自由、不受任何公司或团体所控制。不过,这种免费与开放的精神,却也成了它的弱点。如今我们几乎是自愿地让某些网络运营商控制着我们要去哪里买东西、要看到什么新闻、要对什么人点赞。

在早年网络泡沫时期,有人评论在中国WWW网站的涌现率比人口出生率还高。实际上,我们有世界上最多的用户,但是也有很多的问题。涉及到网络安全,不能不说我们用户和运营商的安全意识还需努力提高。网络安全形势不可小视,蒂姆给我们表示的忧虑不是空穴来风,它预示着互联网新的一波挑战又在开始。不管是加固WWW的系统,还是采用所谓&ldquo;去中心化&rdquo;的架构,我们都拭目以待。

来源:中国科学院高能物理研究所

融云实时语音通话

回复

IM即时通讯admin 回复了问题 • 2 人关注 • 1 个回复 • 65 次浏览 • 2021-04-09 09:49 • 来自相关话题

安卓使用官方的demo好友问题

回复

IM即时通讯北京环球出国 回复了问题 • 3 人关注 • 2 个回复 • 215 次浏览 • 2021-03-04 10:03 • 来自相关话题

详谈HTTPS SSL/TLS协议原理

科技创新森马 发表了文章 • 0 个评论 • 39 次浏览 • 2021-04-28 16:53 • 来自相关话题

协议安全和加密越来越引起人们的重视和关注,今天就跟大家分享一点协议加密方面的知识。要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识。大致了解几个基本术语(HTTPS、SSL、TLS)的含义大致了解 HTTP 和 TCP 的关系(尤其是 “短连接”... ...查看全部

协议安全和加密越来越引起人们的重视和关注,今天就跟大家分享一点协议加密方面的知识。要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识。

  1. 大致了解几个基本术语(HTTPS、SSL、TLS)的含义

  2. 大致了解 HTTP 和 TCP 的关系(尤其是 “短连接”VS“长连接”)

  3. 大致了解加密算法的概念(尤其是 “对称加密与非对称加密” 的区别)

  4. 大致了解 CA 证书的用途考虑到很多技术菜鸟可能不了解上述背景,俺先用最简短的文字描述一下。如果你自认为不是菜鸟,请略过本章节,直接去看 “HTTPS 协议的需求”。

一、先澄清几个术语——HTTPS、SSL、TLS。

1. “HTTP” 是干嘛用滴?

首先,HTTP 是一个网络协议,是专门用来帮你传输 Web 内容滴。关于这个协议,就算你不了解,至少也听说过吧?比如你访问俺的博客的主页,浏览器地址栏会出现如下的网址http://www.xxx.com/

俺加了粗体的部分就是指 HTTP 协议。大部分网站都是通过 HTTP 协议来传输 Web 页面、以及 Web 页面上包含的各种东东(图片、CSS 样式、JS 脚本)。

2. “SSL/TLS” 是干嘛用滴?

SSL 是洋文 “Secure Sockets Layer” 的缩写,中文叫做 “安全套接层”。它是在上世纪 90 年代中期,由网景公司设计的。(顺便插一句,网景公司不光发明了 SSL,还发明了很多 Web 的基础设施——比如“CSS 样式表” 和“JS 脚本”) 为啥要发明 SSL 这个协议捏?因为原先互联网上使用的 HTTP 协议是明文的,存在很多缺点——比如传输内容会被偷窥(嗅探)和篡改。发明 SSL 协议,就是为了解决这些问题。

到了 1999 年,SSL 因为应用广泛,已经成为互联网上的事实标准。IETF 就在那年把 SSL 标准化。标准化之后的名称改为 TLS(是 “Transport Layer Security” 的缩写),中文叫做“传输层安全协议”。

很多相关的文章都把这两者并列称呼(SSL/TLS),因为这两者可以视作同一个东西的不同阶段。

3. “HTTPS” 是啥意思?

解释完 HTTP 和 SSL/TLS,现在就可以来解释 HTTPS 啦。咱们通常所说的 HTTPS 协议,说白了就是 “HTTP 协议” 和“SSL/TLS 协议”的组合。你可以把 HTTPS 大致理解为——“HTTP over SSL”或“HTTP over TLS”(反正 SSL 和 TLS 差不多)。

二、再来说说 HTTP 协议的特点

作为背景知识介绍,还需要再稍微谈一下 HTTP 协议本身的特点。HTTP 本身有很多特点,考虑到篇幅有限,俺只谈那些和 HTTPS 相关的特点。

1. HTTP 的版本和历史

如今咱们用的 HTTP 协议,版本号是 1.1(也就是 HTTP 1.1)。这个 1.1 版本是 1995 年底开始起草的(技术文档是 RFC2068),并在 1999 年正式发布(技术文档是 RFC2616)。

在 1.1 之前,还有曾经出现过两个版本 “0.9 和 1.0”,其中的 HTTP 0.9 没有被广泛使用,而 HTTP 1.0 被广泛使用过。另外,2015年IETF 就要发布 HTTP 2.0 的标准了。

2. HTTP 和 TCP 之间的关系

简单地说,TCP 协议是 HTTP 协议的基石——HTTP 协议需要依靠 TCP 协议来传输数据。在网络分层模型中,TCP 被称为 “传输层协议”,而 HTTP 被称为 “应用层协议”。

有很多常见的应用层协议是以 TCP 为基础的,比如 “FTP、SMTP、POP、IMAP” 等。

TCP 被称为 “面向连接” 的传输层协议。关于它的具体细节,俺就不展开了(否则篇幅又失控了)。你只需知道:传输层主要有两个协议,分别是 TCP 和 UDP。TCP 比 UDP 更可靠。你可以把 TCP 协议想象成某个水管,发送端这头进水,接收端那头就出水。并且 TCP 协议能够确保,先发送的数据先到达(与之相反,UDP 不保证这点)。

3. HTTP 协议如何使用 TCP 连接?

HTTP 对 TCP 连接的使用,分为两种方式:俗称 “短连接” 和“长连接”(“长连接”又称 “持久连接”,洋文叫做“Keep-Alive” 或“Persistent Connection”) 假设有一个网页,里面包含好多图片,还包含好多外部的CSS 文件和 JS 文件。在 “短连接” 的模式下,浏览器会先发起一个 TCP 连接,拿到该网页的 HTML 源代码(拿到 HTML 之后,这个 TCP 连接就关闭了)。然后,浏览器开始分析这个网页的源码,知道这个页面包含很多外部资源(图片、CSS、JS)。

然后针对每一个外部资源,再分别发起一个个 TCP 连接,把这些文件获取到本地(同样的,每抓取一个外部资源后,相应的 TCP 就断开) 相反,如果是 “长连接” 的方式,浏览器也会先发起一个 TCP 连接去抓取页面。但是抓取页面之后,该 TCP 连接并不会立即关闭,而是暂时先保持着(所谓的“Keep-Alive”)。然后浏览器分析 HTML 源码之后,发现有很多外部资源,就用刚才那个 TCP 连接去抓取此页面的外部资源。

在 HTTP 1.0 版本,默认使用的是 “短连接”(那时候是 Web 诞生初期,网页相对简单,“短连接” 的问题不大);到了 1995 年底开始制定 HTTP 1.1 草案的时候,网页已经开始变得复杂(网页内的图片、脚本越来越多了)。这时候再用短连接的方式,效率太低下了(因为建立 TCP 连接是有 “时间成本” 和“CPU 成本”滴)。

所以,在 HTTP 1.1 中,默认采用的是 “Keep-Alive” 的方式。关于 “Keep-Alive” 的更多介绍,可以参见维基百科词条。

三、谈谈 “对称加密” 和“非对称加密”的概念

1. 啥是 “加密” 和“解密”?

通俗而言,你可以把 “加密” 和“解密”理解为某种互逆的数学运算。就好比 “加法和减法” 互为逆运算、“乘法和除法”互为逆运算。

“加密”的过程,就是把 “明文” 变成 “密文” 的过程;反之,“解密”的过程,就是把 “密文” 变为“明文”。在这两个过程中,都需要一个关键的东东——叫做“密钥”——来参与数学运算。

2. 啥是 “对称加密”?

所谓的 “对称加密技术”,意思就是说:“加密” 和“解密”使用相同的密钥。这个比较好理解。就好比你用 7zip 或 WinRAR 创建一个带密码(口令)的加密压缩包。当你下次要把这个压缩文件解开的时候,你需要输入同样的密码。在这个例子中,密码 / 口令就如同刚才说的“密钥”。

3. 啥是 “非对称加密”?

所谓的 “非对称加密技术”,意思就是说:“加密” 和“解密”使用不同的密钥。这玩意儿比较难理解,也比较难想到。当年 “非对称加密” 的发明,还被誉为 “密码学” 历史上的一次革命。

由于篇幅有限,对 “非对称加密” 这个话题,俺就不展开了。有空的话,再单独写一篇扫盲。

4. 各自有啥优缺点?

看完刚才的定义,很显然:(从功能角度而言)“非对称加密”能干的事情比 “对称加密” 要多。这是 “非对称加密” 的优点。但是 “非对称加密” 的实现,通常需要涉及到 “复杂数学问题”。所以,“非对称加密” 的性能通常要差很多(相对于 “对称加密” 而言)。这两者的优缺点,也影响到了 SSL 协议的设计。

四、HTTPS 协议的需求是啥?

花了好多口水,终于把背景知识说完了。下面正式进入正题。先来说说当初设计 HTTPS 是为了满足哪些需求?

很多介绍 HTTPS 的文章一上来就给你讲实现细节。个人觉得:这是不好的做法。早在 2009 年开博的时候,发过一篇<学习技术的三部曲:WHAT、HOW、WHY>,其中谈到 “WHY 型问题” 的重要性。一上来就给你讲协议细节,你充其量只能知道 WHAT 和 HOW,无法理解 WHY。

俺在前一个章节讲了“背景知识”,在这个章节讲了“需求”,这就有助于你理解:当初为什么要设计成这样?——这就是 WHY 型的问题。

兼容性

因为是先有 HTTP 再有 HTTPS。所以,HTTPS 的设计者肯定要考虑到对原有 HTTP 的兼容性。这里所说的兼容性包括很多方面。比如已有的 Web 应用要尽可能无缝地迁移到 HTTPS;比如对浏览器厂商而言,改动要尽可能小;基于 “兼容性” 方面的考虑,很容易得出如下几个结论:

  1. HTTPS 还是要基于 TCP 来传输(如果改为 UDP 作传输层,无论是 Web 服务端还是浏览器客户端,都要大改,动静太大了)。

  2. 单独使用一个新的协议,把 HTTP 协议包裹起来 (所谓的 “HTTP over SSL”,实际上是在原有的 HTTP 数据外面加了一层 SSL 的封装。HTTP 协议原有的 GET、POST 之类的机制,基本上原封不动)。打个比方: 如果原来的 HTTP 是塑料水管,容易被戳破;那么如今新设计的 HTTPS 就像是在原有的塑料水管之外,再包一层金属水管。一来,原有的塑料水管照样运行;二来,用金属加固了之后,不容易被戳破。

可扩展性

前面说了,HTTPS 相当于是 “HTTP over SSL”。如果 SSL 这个协议在 “可扩展性” 方面的设计足够牛逼,那么它除了能跟 HTTP 搭配,还能够跟其它的应用层协议搭配。岂不美哉?

现在看来,当初设计 SSL 的人确实比较牛。如今的 SSL/TLS 可以跟很多常用的应用层协议(比如: FTP、SMTP、POP、Telnet)搭配,来强化这些应用层协议的安全性。

接着刚才打的比方: 如果把 SSL/TLS 视作一根用来加固的金属管,它不仅可以用来加固输水的管道,还可以用来加固输煤气的管道。

保密性

HTTPS 需要做到足够好的保密性。说到保密性,首先要能够对抗嗅探(行话叫 Sniffer)。所谓的 “嗅探”,通俗而言就是监视你的网络传输流量。如果你使用明文的 HTTP 上网,那么监视者通过嗅探,就知道你在访问哪些网站的哪些页面。

嗅探是最低级的攻击手法。除了嗅探,HTTPS 还需要能对抗其它一些稍微高级的攻击手法——比如 “重放攻击”。

完整性

除了 “保密性”,还有一个同样重要的目标是“确保完整性”。关于“完整性” 这个概念,在之前的博文<扫盲文件完整性校验——关于散列值和数字签名>中大致提过。健忘的同学再去温习一下。在发明 HTTPS 之前,由于 HTTP 是明文的,不但容易被嗅探,还容易被篡改。

举个例子: 比如咱们天朝的网络运营商都比较流氓,经常有网友抱怨说访问某网站(本来是没有广告的),竟然会跳出很多广告。为啥会这样捏?因为你的网络流量需要经过 ISP 的线路才能到达公网。如果你使用的是明文的 HTTP,ISP 很容易就可以在你访问的页面中植入广告。所以,当初设计 HTTPS 的时候,还有一个需求是 “确保 HTTP 协议的内容不被篡改”。

真实性

在谈到 HTTPS 的需求时,“真实性”经常被忽略。其实 “真实性” 的重要程度不亚于前面的 “保密性” 和“完整性”。

举个例子: 你因为使用网银,需要访问该网银的 Web 站点。那么,你如何确保你访问的网站确实是你想访问的网站?(这话有点绕口令) 有些天真的同学会说:通过看网址里面的域名来确保。

为啥说这样的同学是 “天真的”?因为 DNS 系统本身是不可靠的(尤其是在设计 SSL 的那个年代,连DNSSEC 都还没发明)。由于DNS 的不可靠(存在“域名欺骗” 和“域名劫持”),你看到的网址里面的域名未必是真实滴!所以,HTTPS 协议必须有某种机制来确保 “真实性” 的需求。

性能

再来说最后一个需求——性能。引入 HTTPS 之后,不能导致性能变得太差。否则的话,谁还愿意用?为了确保性能,SSL的设计者至少要考虑如下几点:

  1. 如何选择加密算法(“对称”or“非对称”)?

  2. 如何兼顾 HTTP 采用的 “短连接”TCP 方式?SSL 是在1995 年之前开始设计的,那时候的 HTTP 版本还是 1.0,默认使用的是 “短连接” 的 TCP 方式——默认不启用 Keep-Alive)。


日志审计系统的基本原理与部署方式

科技创新森马 发表了文章 • 0 个评论 • 34 次浏览 • 2021-04-28 11:43 • 来自相关话题

日志审计系统简介什么是日志审计?综合日志审计平台,通过集中采集信息系统中的系统安全事件、用户访问记录、系统运行日志、系统运行状态等各类信息,经过规范化、过滤、归并和告警分析等处理后,以统一格式的日志形式进行集中存储和管理,结合丰富的日志统计汇总及关联分析功能,... ...查看全部

日志审计系统简介

什么是日志审计?

综合日志审计平台,通过集中采集信息系统中的系统安全事件、用户访问记录、系统运行日志、系统运行状态等各类信息,经过规范化、过滤、归并和告警分析等处理后,以统一格式的日志形式进行集中存储和管理,结合丰富的日志统计汇总及关联分析功能,实现对信息系统日志的全面审计。

通过日志审计系统,企业管理员随时了解整个IT系统的运行情况,及时发现系统异常事件;另一方面,通过事后分析和丰富的报表系统,管理员可以方便高效地对信息系统进行有针对性的安全审计。遇到特殊安全事件和系统故障,日志审计系统可以帮助管理员进行故障快速定位,并提供客观依据进行追查和恢复。[百度百科]

为什么需要日志审计平台?

  1. 日志审计的合规要求,由于网络安全法的颁布实施,由原先的不合规转变成了不合法。如果不对要求的相关日志不做留存6个月以上,一旦追查,将面临法律责任。

  2. 安全运营的挑战。随着网络设备的增多,以及服务器数量的增多,如果没有统一的综合日志审计平台,那么需要登录到每台设备上查看日志,不利于运维人员管理。而且众多设备会产生海量的日志,无法有效管理。多种设备形成信息孤岛,日志无法关联分析。通过统一的日志审计平台,将所有设备日志都收集到日志平台进行统一管理,统一分析。

日志审计的核心目标:

  • 多源数据归一化

  • 日志存储集中化

  • 关联分析自动化

  • 安全态势立体化

日志审计的主要功能

设计思路:

统一日志采集:
  • 对不同日志源 (主机系统、网络设备、安全设备、应用中间件、数据库等)所产生的日志进行收集,实现日志的集中管理和存储。支持解析任意格式、任意来源的日志,通过解析规则标准化。

  • 使用无代理的方式收集日志。

  • 支持代理方式的日志收集。

关联分析:
  • 预置多种事件关联规则。

  • 定位外部威胁、黑客攻击、内部违规操作,设备异常。

  • 简单灵活定义关联规则。

实时告警:
  • 通过邮件、短信、声音对发生的告警进行及时通知,并可通过接口调用自动运行程序或脚本。

  • 通过告警策略定义,对各类风险 和事件进行及时告警或预警,提升运维效率。

日志取证分析:
  • 深入分析原始日志事件,快速定位问题的根本原因。

  • 生成取证报表,例如攻击威胁报表、Windows/Linux系统审计报表以及合规性审计报表等。

监管合规:
  • 提供Windows审计、Linux审计、PCI、SOX、ISO27001等合规性报表。

  • 支持创建自定义合规性报表

日志审计系统产品功能结构:

图:日志审计系统产品功能结构

日志审计系统的主要工作原理是,通过日志采集器,各种设备将日志推送到日志审计平台,然后日志审计平台通过日志解析,日志过滤,日志聚合等进行关联分析,从而进行告警,统计报表,也可以进行资产管理,日志检索等。

日志的转发方式:

日志转发一般可以通过:Syslog转发,Kafka转发,http转发。

日志收集一般支持:Syslog、SNMP等日志协议。

日志审计系统常见模块:

  • 日志事件获取模块:安全事件监控系统是实时掌握全网的安全威胁状况的重要手段之一。通过事件监控模块监控各个网络设备、主机系统等日志信息,以及安全产品的安全事件报警信息等,及时发现正在和已经发生的安全事件,通过响应模块采取措施,保证网络和业务系统的安全、可靠运行。

  • 资产管理模块:资产管理实现对网络安全管理平台所管辖的设备和系统对象的管理。它将其所辖IP设备资产信息按其重要程度分类登记入库,并为其他安全管理模块提供信息接口。

  • 规则库模块:规则库已支持主流网络设备、主机系统、数据库系统等,而且还应涵盖已经部署的安全系统,包括防火墙系统、防病毒系统等。并提供新日志格式适配功能,支持从安全运营中心平台接收新日志解析映射规则配置。用户可以根据该适配功能,对新日志格式进行自行适配。

  • 统计报表功能:具备强大的统计功能,可快速生成多种专业化的报表并支持自定义图表的设定集展示。

  • 权限管理模块:超级管理员可根据用户角色分配平台查看、操作各模块的权限,用户可以访问而且只能访问自己被授权的资源

日志审计平台的部署方式

硬件产品部署方式:

一般日志审计系统采用旁路部署即可,只要到达全部设备网络可通即可。

支持单机部署和分布式部署。


站在变革的十字路口,智慧医院还存在哪些建设误区?

科技创新小小鸟a 发表了文章 • 0 个评论 • 28 次浏览 • 2021-04-27 18:38 • 来自相关话题

在我国医疗信息化发展不断加速的进程上,医院作为连接医患群体、提供医疗服务的前线,似乎也走到了转型升级的十字路口。日前,以“智慧赋能·助力健康中国”为主题的2021全国智慧医院建设大会在上海召开,众多医疗从业者、云服务商、高校学者等共同聚焦医疗卫生事业,围绕智慧... ...查看全部

在我国医疗信息化发展不断加速的进程上,医院作为连接医患群体、提供医疗服务的前线,似乎也走到了转型升级的十字路口。

日前,以“智慧赋能·助力健康中国”为主题的2021全国智慧医院建设大会在上海召开,众多医疗从业者、云服务商、高校学者等共同聚焦医疗卫生事业,围绕智慧医院的建设思路展开了讨论和探索。

其中,中软国际云智能业务集团以其携手华为打造的智慧医院标杆项目“广东省第二人民医院”为例,重点提出了“全场景智慧、全要素协同、全业务运营,打造全场景智能医院”的观点,为下一代智慧医院的发展提供了诸多实践经验和建设思路。

不难发现,聚焦此次会议,伴随着产业融合趋势的来临,越来越多的医院走上了智能化转型的道路,而同时也有更多的云服务商投身其中,为智慧医院建设提供一体化解决方案,共同推动医疗信息化改革。

那么,在这样的驱动下,我国智慧医院是否能迎来一个光明的未来呢?

1 传统医院,是否到了变革的十字路口?

未来如何,得先确定一下未来是否会来,是否存在足够的条件支持传统医院走上转型升级的道路。

当前,我国正处于智慧医院建设的第一阶段。随着疫情防控的常态化开展、十四五规划的逐步落实,聚焦智慧医疗改革必然成为未来社会发展的关键方向。

事实上,近两年来,我国也一直在政策层面对智慧医院建设施加正向推力。在2018年,国务院办公厅便印发了《关于促进“互联网+医疗健康”发展的意见》,明确指出到2020年,二级以上医院普遍提供分时段预约诊疗、智能导医分诊、候诊提醒、检验检查结果查询、诊间结算、移动支付等线上服务,积极发展“互联网+医疗健康”,引入优质医疗资源,提高医疗健康服务的可及性。

因此,有了明确的发展方向,伴随着AI、5G、云计算、大数据等前沿技术的快速发展和深化应用,“互联网+”也顺势迭代升级至“AI+”。更多新技术的底层支持,促使医疗信息化改革面向医院场景实现了更全面的智能化转型。

在广东省第二人民医院,中软国际云智能业务集团携手华为通过整合AI、云、大数据等前沿技术,打造并应用了医院智慧运营中心HOC大脑,使得院区内防疫、安防、消防等各环节实现了一屏精准化管理,突破了传统医院的管理模式。

而这样的实践,也使得智慧医疗的市场加速扩容。据中国电子学会统计的最新数据显示,到2021年医疗人工智能行业市场规模将会达到75.3亿元。那么,新需求的增长吸引着更多医疗从业者和云服务商涌向这个市场,商业化的驱动使得智慧医院的建设进入一个更加良性的发展阶段。

目前,中软国际云智能业务集团等云服务商正是在这样的发展下,积极参与到智慧医院的建设,通过技术和运营的方式和传统医院联合,共同推动医疗的信息化改革。

总的来说,在十四五规划的开局之年,智慧医院建设的各方面条件都有了相对比较成熟的基础,政策上的正向推力、技术上的应用落地和市场上的商业驱动等等,都促使着智慧医院必然会成为未来发展的大趋势。

2 智慧医院,还存在哪些建设误区?

趋势可以判断,而过程又该如何展开?智慧医院建设本身就是一个驳杂多元的系统,且不说传统医院体系交叠复杂,就智能化的建设而言也面临着多方协调、长期投入的难点。

在这个道路上,注定不会简单。在此,我们或许可以从三个关键词来思考一下,智慧医院发展还存在着哪些建设上的误区?

1.     底座:光想着“建高楼”,不可忽视了“打基础”。

很多时候,传统行业的智能化升级不能只是原地起高楼,光想着在传统模式上部署项目、落实技术是不行的,新旧结合意味着流程重塑,还必须得统筹全局,打好基础。

比如,如果只是在原来的各个节点部署新系统,是否可以建设好智慧医院?答案是不能的。对此,中软国际云智能业务集团选择了以HOC大脑+八大应用+数字平台为主的顶层设计,实现院区从门诊到住院、从诊疗到科研、从患者体验到医护效率的全智能化覆盖,赋能医院从粗放式向精细化转变。

同时,“打基础”还不只是顶层设计的问题,从长远目标来看,更是整个医疗系统的全方位转型落实。因此,中软国际云智能业务集团在打造智慧院区解决方案上,重点也将云、AI、5G、大数据等技术应用于医、教、研、管等各个领域,做好各方面的转型工作。

以“研”来说,医药研发是日常患者并不关注的领域,但确是推动医疗行业发展的基础。将新技术应用于基础领域,正是立足在医疗行业的全局发展,从最核心的环节做好技术赋能。也只有把基础打好了,才能保证智慧医院的“高楼”建设稳定而又高效,这便是“底座”的价值。

2.    场景:哪些群体才是智慧医院的服务对象?

医院是面向患者的服务场景,而智慧医院不然,其需要面向患者,也需要面向医护人员、医院管理者、医联体等多个主体。因此,明确哪些群体才是智慧医院的服务对象至关重要。

如果无法兼顾多个服务对象,智慧化升级终究是不完整的,智慧医院也就名不副实。这也是为什么中软国际云智能业务集团致力于打造“全场景智能医院”的初衷。

面向患者,需要打造全流程智能就医,优化就诊体验;面向医护,需要打造智能工作站,辅助贯穿诊疗全流程;面向医院管理者,需要打造全方位可视、可管、可控的服务能力,推动精细化管理,等等。中软国际云智能业务集团在打造全场景智能医院时,正是明确了这些服务对象,进而针对特定的群体开展系统部署,提供全面的智能化升级服务。

中软国际云智能业务集团执行总裁孙佳韡认为,“这段时期,人们更多是给数字经济未来的腾飞建设一条相互连接公路,只有“路”修通了,数字经济才有了基础,人们才会真正认识到其所带来的新机会。”

很显然,对于智慧医院建设而言,需要搭建的正是让每一个对象触达智慧医院的“公路”,只有每一个人脚下的“路”修通了,智慧医院的成果才能真正惠及到社会。

3.    生态:”单打独斗”已成过去式,协同的价值可以发挥几何?

总的来说,智慧医院建设一个既宽泛也很有纵深的工程,这也决定了其必然需要一个长期的投入和布局。因此,在智慧医院的建设历程上,仅是一个人的单打独斗很乏力,更多是基于生态联合,整合优势才能撑起医院系统全方位的智能化。

因此,中软国际云智能业务集团在打造全场景智能医院的过程,也携手华为强强联合推动医疗信息化改革。此次2021全国智慧医院建设大会的召开,也正是希望在经验交流中集思广益,让更多的从业者看到合作的希望,通过生态整合来推动智慧医院的落地。

思维导向驱动发展进程。中软国际云智能业务集团所构想的“全场景智能医院”既然要全面,就必然需要连同更多的生态伙伴,在专业分工下打造完整的医院智能系统。

事实上,伴随着传统产业的智能化改革,这样生态路径会是常态,也是主流。这也意味着,智能化升级考验的不仅是自家的能力,也挑战者生态的水平,谁能携手更多更优质的生态伙伴,谁就拥有更大的市场优势。

3 下一代更智慧的医院,还有多远?

目前,我国智慧医院建设才刚刚起步,从三个关键词来看,建设者需要避免进入“基础不牢”、“服务对象不清晰”、“个人单打独斗”的误区。而做好底座建设、场景布局和生态合作三个层面的工作,也意味着智慧医院并非一蹴而就。

但也并不是遥不可及。中软国际云智能业务集团携手华为广东省第二人民医院打造智慧院区项目已取得了不错的反馈。据官方数据显示,基于智慧化升级,院区安保成本下降15%,能耗成本下降10%,就医时间成本减少了0.5h。

可见,在稳步的建设推动下,智慧医院相较于传统医院,正在持续优化院区管理和就医体验。只要伴随着前沿技术的深化应用和流程设计的科学部署,智慧医院将会从更多的层面推动医院系统和诊疗服务实现更便捷、高效的发展。

而在这个过程,更多的建设者需要看到智慧医院发展的误区,能笃定智慧医院的未来,并从前沿技术、诊疗流程、管理领域、生态伙伴等多个层面切实推动医院转型升级,才能迎来一个更智慧的未来医院。


从“十四五”规划看去中心化云计算的崛起

科技创新小小鸟a 发表了文章 • 0 个评论 • 33 次浏览 • 2021-04-27 18:12 • 来自相关话题

云计算发展如火如荼,但这个“云计算”却实际上被默认为“中心化”云计算,即集中化、统一归属的远程集群计算。然而,一种“去中心化”云计算正在快速兴起,成为不可忽视的力量。在十四五规划纲要中,2025年我国的数字经济核心产业增加值占GDP比重要从7.8%提升至10%... ...查看全部

云计算发展如火如荼,但这个“云计算”却实际上被默认为“中心化”云计算,即集中化、统一归属的远程集群计算。然而,一种“去中心化”云计算正在快速兴起,成为不可忽视的力量。

在十四五规划纲要中,2025年我国的数字经济核心产业增加值占GDP比重要从7.8%提升至10%,这其中,云计算、区块链等技术毫无疑问是建设数字中国的重要技术载体,在推动政企数字化变革、激发数字化技术与商业模式创新等方面有关键的作用。

区块链底层技术+云计算模式形成的“去中心化云计算”在产业政策导向下,大量玩家纷纷入局,以期在这个新领域占据先机、成为另一种形式的云计算巨头。

这包括想要成为“永不宕机的阿里云”的AELF区块链项目,号称要对标谷歌云、微软云的DADI区块链项目,以及自称“全球首家泛载雾计算平台”的博纳云(BonusCloud)、定位自己为“全球首个去中心化的云计算市场”的Akash(主要为DeFi提供去中心化云服务,即DeCloud)等。

而其中,有不少项目或企业已经进入实质性的应用阶段,取得了不错的市场成绩。例如宣称要做“去中心化云计算一站式服务领军者”的安迈云,其产品和解决方案在很多企业中得到落地应用。

以去中心化技术重构信任与安全,重塑传统集中式云计算的业务模型和资源分配结构,去中心化云计算正在推动数字经济更好、更快速地实现。

1 数字经济被提到新的高度,倒逼去中心化云计算快速发展?

一边是数字经济被列入未来宏观发展规划,另外一边,在数字经济推进过程中,很多挑战也逐渐显露出来,尤其是作为存储与计算发展主要力量的云计算,在应用到政企数字化转型过程中,出现很多亟待优化和解决的问题。在十四五规划的单列篇章五中,就对云计算发展有专门的论述,包括加快云操作系统迭代升级,推动超大规模分布式存储、弹性计算、数据虚拟隔离等技术创新,提高云安全水平等。

从这个意义上看,去中心化云计算的发展,首先通过帮助政企更好地实现数字化转型,契合了数字经济进一步发展的特征,从而实现了快速发展,这某种程度上是需求倒逼的结果。

1、成本:既要关注当下业务需求,更需要关注扩展需要

政企数字化越是往深处走,中心化云计算在成本方面的挑战就是凸显:如果说云计算相对于本地部署在成本上有巨大优势,那么当政企数字化走向深入后,复杂计算、大规模计算、海量数据存储等将同样给企业带来越来越沉重的负担。

较为典型的,如工业互联网建设,企业不得不为此在云计算上投入巨大的存储和计算成本。

而去中心化云计算由于采用的是分布式、不需要大批量基础设施建设的存储和计算节点,在成本上有巨大的优势,那些存储和计算规模庞大、任务繁重的企业,采用去中心化云计算将直接节约成本。

更进一步来看,由于去中心化的技术特性(个体节点、充分细分),当企业想要将存储和计算规模扩大(这是常态)时,在边际成本上也将变得更低。

如此,在门槛更低的情况下,政企组织接入云计算变得更容易,数字经济的规划落地也就扫除了参与度的障碍。

2、安全:既需要总体运行的安全,更需要个体数据的安全

云计算,或者说中心化云计算似乎生来就带有安全方面的挑战。

一方面,由于存储、计算的集中化,大量政企组织依赖一个平台,当中心化的平台出现运行问题,就会殃及几乎所有被服务方——中心化云计算的规模做得越大,这种运行方面安全问题的隐忧就越大。那些大型云计算平台的宕机事件每每都能成为业界“大新闻”,100%地把自己的身家性命压在了第三方服务器上的企业很难承受这样的宕机事故,但事故又层出不穷,受限于中心化的机制难以在根本上避免。

这时候,去中心化云计算的优势显露出现,分散的节点使得去中心化云计算理论上可以做到永不宕机,这是一种机制上的先天优势。

另一方面,在数据的归属上,客户与中心化云计算平台之间存在微妙的关系,上传的文件、处理业务的数据沉淀如何保证隐私性和安全性是政企客户常常考虑的问题,很多时候数据安全的保障甚至只能靠中心化平台的“自觉”,这显然不符合数字经济时代的需要。

3、体验:既需要灵活多样的弹性服务,更需要定制化的专业服务

尽管传统中心化云计算一直在进行弹性存储和计算方面的技术更新,但这种弹性往往只是尽可能拟合现实需要,企业实际应用时,在需要变动十分复杂时,还是会不可避免地出现配置资源不足或浪费的情况。

这是由于传统中心化云计算一般都是先有订单再有服务,资源的配置需要系统的划分,弹性调整需要极为复杂的技术来实现,往往无法做到真正的“要多少、给多少、收多少费用”。

而去中心化云计算由于节点被最大程度分散,在低颗粒度的情况下,弹性服务的提供上更有潜力。

此外,数字化转型走向深入后,很多政企组织对定制化服务的需求越来越显著,契合自身需要的产品和解决方案变得更重要,但在中心化情况下,这可能是属于大客户才能享有的待遇。

在去中心化云计算这里,情况或能够得到改善,例如,安迈云构建的去中心化云计算产品体系中,类似IPFS基础设施解决方案这种服务,能够很好地利用去中心化的高可用性、资源独享、部署灵活等特征,为客户定制优化的分布式存储的解决方案。

总得看来,在宏观政策导向下,“传统”中心化云计算与“政策期望”之间的差距,正在被去中心化云计算所弥合。

2 区块链价值落地,给去中心化云计算带来新的价值想象空间?

不可忽视的是,去中心化云计算本质可以算是区块链技术的一个重要应用,从区块链的角度看,它则是中国乃至全球区块链产业蓬勃发展的代表,成为业界所期待的有效落地项目之一。

而正是从这个角度,而不是单纯从云计算角度看,去中心化云计算又可以为数字经济带来新的价值想象空间。

1、数字资产流转新蓝海,需要新的基础设施

数据隐私的保护其实背后暗含另一层意义,即数据资产的归属与处置问题。隐私得到很好的保护,会使得用户将数据的价值控制在自己手中,从而催生商业模式创新。

在区块链技术的加持下,去中心化云计算中的数据,有机会完成中心化云计算难以完成的数据资产确权等工作,用户在链上可以便捷、安全地向第三方有偿分享数据信息,从而让自己的数据池变成某种数字资产,换取收益。

在这种情况下,国家大力倡导的数字经济,在数据底层原料层面将变得更加有活力。

2、多样性计算各有所长,计算与硬件匹配才能大大提升效率

云计算的底层架构,在传统的X86之外,近年来ARM等架构的计算芯片崛起,且厂商众多。在分布式云计算中,由于参与成为节点的硬件各异,使得用户总能够根据自身的需要,在链上找到对应的、能够最大程度发挥芯片架构优势加速运行效率的计算硬件,使得计算找到最好的硬件匹配。

换言之,用户不但可以快速进行横向的计算能力扩展,也更容易找到效果更好、成本控制更优的多样化计算硬件。

而对比来看,很多中心化云计算平台还在为了多样性计算的兼容而投入大量资源。

3、特殊数字场景凸显“既要……又要……”难题,亟待解决

随着数字经济走向全领域、全场景,很多过去被认为是云计算“禁区”的特殊数字场景,也不得不顺应时代需求进行变革升级,金融场景最为典型。

出于监管的需要,过去在金融领域,数据必须放在本地,很难进行远程外部机房的连接访问工作,这影响了计算效率的发挥,让银行等核心金融机构在数字化这件事上似乎总是慢半步。

现在,去中心化云计算借助安全、保密难以被攻破的区块链技术,能最大程度保证金融数据安全,同时扩展更多存储与计算服务。

类似的场景还有更多,这些最难的堡垒打下来后,数字经济才能真正实现落地。

3 搭上趋势快车,但去中心化云计算“颠覆”却不“替代”?

毫无疑问,与传统的云计算相比,去中心化云计算是一种模式上的颠覆,是区块链技术的重要落地应用,最大程度契合了宏观政策对云计算推动数字经济发展的期盼。

但是,必须看到的是,同样在政策导向下,去中心化云计算却并不对传统中心化云计算形成替代,只是在补足后者无法很好地满足的领域,共同服务于数字经济时代。所以,中心化与去中心化云计算的并存将成为一种常态,有业内人士认为,二者将凭借各自优势分享市场(例如,中心化云计算在社交、电商这类实时、复杂、高频应用中有天然优势),各占50%的份额。

甚至,去中心化云计算中的IPFS作为一个面向全球的、点对点的分布式版本文件系统,其有不少节点使用的是微软、谷歌、阿里云等公司的云服务器(这并不违背去中心化原则,中心化的平台所提供的存储和计算服务只作为一个节点存在),这种特殊的关系证明了二者的共存将是未来的常态。

当去中心化云计算平台逐步发展起来,可以发现,它们并不是搅局者,而是为云计算多走出一条路、创造“另一个未来”。但无论如何,这个市场都足够广阔,新的巨头料将出现,在经历缓慢发展后(IPFS去中心化的核心组件开发已经8年之久),去中心化云计算的爆发可能即将来临。


什么是充血模型?什么又是贫血模型?

科技创新柠檬^ 发表了文章 • 0 个评论 • 35 次浏览 • 2021-04-27 17:23 • 来自相关话题

贫血模型即事务脚本模式充血模型即领域模型模式贫血模型最早广泛应用源于EJB2,最强盛时期则是由Spring创造,把“行为”(逻辑、过程)“状态”(数据,对应到语言就是对象成员变量)分离到不同的对象中:只有状态的对象就是所谓的“贫血对象”(常称为VO——Valu... ...查看全部
  • 贫血模型即事务脚本模式

  • 充血模型即领域模型模式

贫血模型

最早广泛应用源于EJB2,最强盛时期则是由Spring创造,把

  • “行为”(逻辑、过程)

  • “状态”(数据,对应到语言就是对象成员变量)

分离到不同的对象中:

  • 只有状态的对象就是所谓的“贫血对象”(常称为VO——Value Object)

  • 只有行为的对象就是我们常见的N层结构中的Logic/Service/Manager层(对应到EJB2中的Stateless Session Bean)。(曾经Spring的作者Rod Johnson也承认,Spring不过是在沿袭EJB2时代的“事务脚本”,也就是面向过程编程)

贫血领域模型是一个存在已久的反模式,目前仍有许多拥趸者。Martin Fowler曾经和Eric Evans聊天谈到它时,都觉得这个模型似乎越来越流行了。作为领域模型的推广者,他们觉得这不是一件好事。

贫血领域模型的基本特征是:它第一眼看起来还真像这么回事儿。项目中有许多对象,它们的命名都是根据领域来的。对象之间有着丰富的连接方式,和真正的领域模型非常相似。但当你检视这些对象的行为时,会发现它们基本上没有任何行为,仅仅是一堆getter/setter。其实这些对象在设计之初就被定义为只能包含数据,不能加入领域逻辑。这些逻辑要全部写入一组叫Service的对象中。这些Service构建在领域模型之上,使用这些模型来传递数据。

这种反模式的恐怖之处在于,它完全和面向对象设计背道而驰。面向对象设计主张将数据和行为绑定在一起,而贫血领域模型则更像是一种面向过程设计,Martin Fowler和Eric在Smalltalk时就极力反对这种做法。更糟糕的时,很多人认为这些贫血领域对象是真正的对象,从而彻底误解了面向对象设计的涵义。

如今,面向对象的概念已经传播得很广泛了,而要反对这种贫血领域模型的做法,还需要更多论据。贫血领域模型的根本问题在于,它引入了领域模型设计的所有成本,却没有带来任何好处。最主要的成本是将对象映射到数据库中,从而产生了一个O/R(对象关系)映射层。只有当你充分使用了面向对象设计来组织复杂的业务逻辑后,这一成本才能够被抵消。如果将所有行为都写入到Service对象,那最终你会得到一组事务处理脚本,从而错过了领域模型带来的好处。正如martin在企业应用架构模式一书中说到的,领域模型并不一定是最好的工具。

将行为放入领域模型,这点和分层设计(领域层、持久化层、展现层等)并不冲突。因为领域模型中放入的是和领域相关的逻辑——验证、计算、业务规则等。如果你要讨论能否将数据源或展现逻辑放入到领域模型中,这就不在本文论述范围之内了。

一些面向对象专家的观点有时会让人产生疑惑,他们认为的确应该有一个面向过程的服务层。但是,这并不意味着领域模型就不应该包含行为。事实上,service层需要和一组富含行为的领域模型结合使用。

Eric Evans的Domain Driven Design一书中提到:

  • 应用层(即Service层)

描述应用程序所要做的工作,并调度丰富的领域模型来完成它。这个层次的任务是描述业务逻辑,或和其它项目的应用层做交互。这层很薄,不包含任何业务规则或知识,仅用于调度和派发任务给下一层的领域模型。这层没有业务状态,但可以为用户或程序提供任务状态。

  • 领域层(或者叫模型层)

表示业务逻辑、业务场景和规则。该层次会控制和使用业务状态,即使这些状态最终会交由持久化层来存储。总之,该层是软件核心。

服务层很薄——所有重要的业务逻辑都写在领域层。他在服务模式中复述了这一观点:如今人们常犯的错误是不愿花时间将业务逻辑放到合适的领域模型中,从而逐渐形成面向过程的程序设计。

我不清楚为什么这种反模式会那么常见。我怀疑是因为大多数人并没有使用过一个设计良好的领域模型,特别是那些以数据为中心的开发人员。此外,有些技术也会推动这种反模式,比如J2EE的Entity Bean,这会让我更倾向于使用POJO领域模型。

总之,如果你将大部分行为都放置在服务层,那么你就会失去领域模型带来的好处。如果你将所有行为都放在服务层,那你就无可救药了。

优点

简单

  • 对于只有少量业务逻辑的应用来说,使用起来非常自然

  • 开发迅速,易于理解

  • 注意:也不能完全排斥这种方式

缺点

无法良好的应对复杂逻辑

  • 比如收入确认规则发生变化,例如在4月1号之前签订的合同要使用某规则…..

  • 和欧洲签订的合同使用另外一个规则…..

充血模型

面向对象设计的本质:“一个对象是拥有状态和行为的”,比如一个人:

  • 他眼睛什么样鼻子什么样这就是状态

  • 人可以去打游戏或是写程序,这就是行为

为什么要有一个“人Manager”这样的东西存在去帮人“打游戏”呢?举个简单的J2EE案例,设计一个与用户(User)相关功能。传统的设计一般是:

  • 类:User+UserManager

  • 保存用户调用:userManager.save(User user)

充血的设计则可能会是:

  • 类:User

  • 保存用户调用:user.save()

  • User有一个行为是:保存它自己

其实它们没有什么特别适用的方向,个人更倾向于总是使用充血模型,因为OOP总是比面向过程编程要有更丰富的语义、更合理的组织、更强的可维护性—当然也更难掌握。因此实际工程场景中,是否使用,如何使用还依赖于设计者以及团队充血模型设计的理解和把握,因为现在绝大多数J2EE开发者都受贫血模型影响非常深。另外,实际工程场景中使用充血模型还会碰到很多很多细节问题,其中最大的难关就是“如何设计充血模型”或者说“如何从复杂的业务中分离出恰到好处且包含语义的逻辑放到VO的行为中”。

如果一个对象包含其他对象,那就将职责继续委托下去,由具体的 POJO 执行业务逻辑,将策略模式更加细粒度,而不是写 ifelse。


分页场景(limit, offset)为什么会慢?

科技创新大神庵 发表了文章 • 0 个评论 • 38 次浏览 • 2021-04-27 17:11 • 来自相关话题

从一个问题说起五年前发现分页场景下,mysql请求速度非常慢。数据量只有10w的情况下,select xx from 单机大概2,3秒。我就问我导师为什么,他反问“索引场景,mysql中获得第n大的数,时间复杂度是多少?”答案的追寻确认场景假设status上面... ...查看全部
从一个问题说起

五年前发现分页场景下,mysql请求速度非常慢。数据量只有10w的情况下,select xx from 单机大概2,3秒。我就问我导师为什么,他反问“索引场景,mysql中获得第n大的数,时间复杂度是多少?”

答案的追寻
确认场景

假设status上面有索引。select * from table where status = xx limit 10 offset 10000。会非常慢。数据量不大的情况就有几秒延迟。

小白作答

瞎猜了个log(N),心想找一个节点不就是log(N)。自然而然,导师让我自己去研究。

这一阶段,用了10分钟。

继续解答

仔细分析一下,会发现通过索引去找很别扭。因为你不知道前100个数在左子树和右子数的分布情况,所以其是无法利用二叉树的查找特性。通过学习,了解到mysql的索引是b+树。

看了这个图,就豁然开朗了。可以直接通过叶子节点组成的链表,以o(n)的复杂度找到第100大的树。但是即使是o(n),也不至于慢得令人发指,是否还有原因。

这一阶段,主要是通过网上查资料,断断续续用了10天。

系统学习

这里推荐两本书,一本《MySQL技术内幕 InnoDB存储引擎》,通过他可以对InnoDB的实现机制,如mvcc,索引实现,文件存储会有更深理解。

第二本是《高性能MySQL》,这本书从着手使用层面,但讲得比较深入,而且提到了很多设计的思路。

两本书相结合,反复领会,mysql就勉强能登堂入室了。

这里有两个关键概念:

  • 聚簇索引:包含主键索引和对应的实际数据,索引的叶子节点就是数据节点

  • 辅助索引:可以理解为二级节点,其叶子节点还是索引节点,包含了主键id。

即使前10000个会扔掉,mysql也会通过二级索引上的主键id,去聚簇索引上查一遍数据,这可是10000次随机io,自然慢成哈士奇。这里可能会提出疑问,为什么会有这种行为,这是和mysql的分层有关系,limit offset 只能作用于引擎层返回的结果集。换句话说,引擎层也很无辜,他并不知道这10000个是要扔掉的。以下是mysql分层示意图,可以看到,引擎层和server层,实际是分开的。

直到此时,大概明白了慢的原因。这一阶段,用了一年。

触类旁通

此时工作已经3年了,也开始看一些源码。在看完etcd之后,看了些tidb的源码。无论哪种数据库,其实一条语句的查询,是由逻辑算子组成。

逻辑算子介绍 在写具体的优化规则之前,先简单介绍查询计划里面的一些逻辑算子。

  • DataSource 这个就是数据源,也就是表,select * from t 里面的 t。

  • Selection 选择,例如 select xxx from t where xx = 5 里面的 where 过滤条件。

  • Projection 投影, select c from t 里面的取 c 列是投影操作。

  • Join 连接, select xx from t1, t2 where t1.c = t2.c 就是把 t1 t2 两个表做 Join。

选择,投影,连接(简称 SPJ) 是最基本的算子。其中 Join 有内连接,左外右外连接等多种连接方式。

select b from t1, t2 where t1.c = t2.c and t1.a > 5 变成逻辑查询计划之后,t1 t2 对应的 DataSource,负责将数据捞上来。上面接个 Join 算子,将两个表的结果按 t1.c = t2.c连接,再按 t1.a > 5 做一个 Selection 过滤,最后将 b 列投影。下图是未经优化的表示:

所以说不是mysql不想把limit, offset传递给引擎层,而是因为划分了逻辑算子,所以导致无法直到具体算子包含了多少符合条件的数据。

怎么解决

《高性能MySQL》提到了两种方案

方案一

根据业务实际需求,看能否替换为下一页,上一页的功能,特别在ios, android端,以前那种完全的分页是不常见的。这里是说,把limit, offset,替换为>辅助索引(即搜索条件)id的方式。该id再调用时,需要返回给前端。

方案二

正面刚。这里介绍一个概念:索引覆盖:当辅助索引查询的数据,只有id和辅助索引本身,那么就不必再去查聚簇索引。

思路如下:`select xxx,xxx from in (select id from table where second_index = xxx limit 10 offset 10000)“ 这句话是说,先从条件查询中,查找数据对应的数据库唯一id值,因为主键在辅助索引上就有,所以不用回归到聚簇索引的磁盘去拉取。再通过这些已经被limit出来的10个主键id,去查询聚簇索引。这样只会十次随机io。在业务确实需要用分页的情况下,使用该方案可以大幅度提高性能。通常能满足性能要求。


继Elastic怒喷云服务商白嫖之后,AWS 终于退出ES的开源分支:OpenSearch!

科技创新大神庵 发表了文章 • 0 个评论 • 34 次浏览 • 2021-04-27 17:11 • 来自相关话题

一直关注DD的朋友应该还记得,今年年初时Elastic公司曾宣布改变其名下的开源协议,而对此AWS(Amazon Web Services——Amazon云服务)就随即表示自己将在仍为开源状态的 Elasticsearch 和 Kibana( 7.10 版本)... ...查看全部

一直关注DD的朋友应该还记得,今年年初时Elastic公司曾宣布改变其名下的开源协议,而对此AWS(Amazon Web Services——Amazon云服务)就随即表示自己将在仍为开源状态的 Elasticsearch 和 Kibana( 7.10 版本)创建分支,今后自己来维护这个分支,做到真正的开源。

转眼间已经过了快三个月,当初的这个真正的开源事件就在近日有了下文。

4月12号,AWS官方宣布推出 OpenSearch 项目!

根据AWS的官方介绍,OpenSearch 项目由OpenSearch和OpenSearch Dashboards组成,这两项的确也都是基于当初所说的Elasticsearch 和 Kibana( 7.10.2 版本)。

项目均采用Apache License 2.0 开源许可协议,功能完成度也不少,包括像企业安全、告警、机器学习、SQL、索引状态管理等,应有尽有。

而针对Elasticsearch之前的改变以及自己的真开源讲法,AWS表示OpenSearch虽然时基于Elasticsearch,但是删除了其中和Elastic有关的商业许可证限制、代码、商标等,在采用了Apache License 2.0 之后,OpenSearch可以让每个用户都毫无负担的构建和创新,而不用再担心一些贡献之外的问题。

同时,AWS还宣布现有的 Amazon Elasticsearch Service,将会变更名号,成为一个崭新的Amazon OpenSearch Service!

更名之后的Amazon OpenSearch Service,想必是为了摆脱和Elasticsearch的关联,在不影响正在运营业务的前提下,还会提供一系列可供部署和运行的开源引擎,包括当前可用的 19 个版本的 Elasticsearch(7.9 和更早版本、近期推出的 7.10)以及新版本的 OpenSearch。

为了满足现有用户的使用需要,AWS还宣布未来的Amazon OpenSearch Service API 将与现有服务 API 完美兼容,还会为用户提供将现有 Elasticsearch 6.x 和 7.x 托管集群迁移至 OpenSearch 的无缝升级路径。

可能在未来的几周内,我们就能见到AWS发布 Beta 版本,根据AWS的展望,预计在2021年中期发布稳定版并投入生产环境使用。

随着AWS的声明,不少公司都纷纷站队表示支持,像红帽、SAP、Capital One 和 Logz.io 都是其坚定的盟友。

红帽表示:

我们感谢亚马逊对开放搜索的承诺,我们很高兴看到亚马逊继续支持开源

SAP表示:

SAP客户期望一个统一的、以业务为中心的、开放的SAP业务技术平台。OpenSearch提供了一个真正的开源途径和社区驱动的方法来推动这一进程。

Capital One说到:

我们非常支持OpenSearch项目,因为它将使我们能够更好地控制和自主选择数据平台,同时保留开放源代码许可证提供的自由。

而第一个站出来吐槽Elastic公司的Logz.io则发言:

我们承诺与AWS和社区其他成员合作,创新并使世界各地的每个组织都能享受这些关键的开源项目带来的好处。

那到底AWS的OpenSearch能不能达到大家的预期呢?我们拭目以待!


浅谈Spring MVC 过时了吗?

科技创新fanta2 发表了文章 • 0 个评论 • 45 次浏览 • 2021-04-16 14:47 • 来自相关话题

正文如下:问题:Spring MVC 过时了吗?我看了一下这个问题的日志,这个问题是2018年9月提出来的。那么好,首先给出结论:Spring MVC没有过时,它仍然是当前主流的Java Web开发框架。但是,在这个时间点谈论这个问题就有点意思了。题主提出这个... ...查看全部

正文如下:

问题:Spring MVC 过时了吗?

我看了一下这个问题的日志,这个问题是2018年9月提出来的。

那么好,首先给出结论:Spring MVC没有过时,它仍然是当前主流的Java Web开发框架。但是,在这个时间点谈论这个问题就有点意思了。题主提出这个问题的时候,可能都没有意识到这个问题正处在Web开发思想变革的分水岭上。

首先,说一下答主这个问题描述中不准确的地方,后面再着重说说现在的分水岭。

现在jsp似乎已经渐渐淡出大家的视野。web开发朝着前后端分离的方向去了

这个没错。但是,

像spring mvc这样前后端耦合较大的框架是否过时了?

这个疑问就没有必要了。

Spring MVC前后端耦合不大啊。你完全可以使用@RestController。

@RestControlleris a specialized version of the controller. It includes the @Controller and @ResponseBody annotations and as a result, simplifies the controller implementation:

@RestController@RequestMapping(“books-rest”)public class SimpleBookRestController {           @GetMapping(“/{id}”, produces = “application/json”)     public Book getBook(@PathVariable int id) {         return findBookById(id);     }       private Book findBookById(int id) {         // …    } }

前后端分离,没有JSP或其他服务器端模板引擎,只有HTTP上传输的JSON交互,那么必然用@RestController。JSON是服务器端MVC框架的V,是前端MVC框架的M。

————–重点开始————-

下面说一下为什么现在这个问题比较有意思了。

因为从Spring 5开始,大量引入了Reactive概念,也就是响应式思想!!!

所以,Spring 4及以前版本长期存在的Spring MVC有了一个并列同时存在的新的编程模型,Spring WebFlux。

上图,左侧是新的Spring WebFlux,可以看出一切都是Reactive的。右侧是我们熟悉的Spring MVC,是基于Servlet API的。

这个问题下的其他回答,竟然还在问:

那你是觉得哪个框架替代了Spring MVC?

你能找出其他框架来代替它吗?如果没有,那就没有过时

你们最近半年访问过Spring 官网首页吗?

特别是2018的Spring One大会,大家注意到了吗?看一下所有的话题(session),多少题目里都包含了Reactive:

所以,如果Spring认定了Reactive是趋势的话,传统的Spring MVC应该是处于Deprecated状态。上图中两种模型可能会长期并存,但是Spring 6以后就不好说了~

在今年的Spring One大会上,Spring提出了一整套Reactive技术,Spring 自己称作Reactive Revolution:

还有更多的Reactive思想涌现出来了,大家要保持关注。

不仅仅是服务器端,前端的Reactive也很活跃,例如Rxjs。

正如Spring自己定义的那样,现在是一场Reactive Revolution,这场思想革命波及Web开发的全栈,数据库=>服务器=>前端。

所以,此时想一下Spring MVC是否过时是个很有意思的问题。它仍是最主流最成熟的Java服务器端MVC框架,但它并不代表Web进化的方向。

评论区有人提到Vert.x。到目前Vert.x也只是个tool-kit,不适一整套框架。现在技术讲求的是生态环境,Spring现在基本上是占有生态优势,有Spring MVC的普及率。不管Spring MVC还是Web Flux,都能融入这个生态,Spring Boot都会给予先天的支持。

回复@无忧

编程首先思想活动,然后才是敲代码。学习编程的语言、框架等等,首先是思想跟上。比如前端用惯了JQuery的人,直接操作DOM,让他们学习Angular、VUE这总双向绑定,肯定也会觉得反直觉。但是说到底,思想在进步,落后的思想就会觉得先进思想反直觉。民国时期,多少人看到女人穿泳衣游泳也觉得反直觉,但是现在都是正常的。

生态也不是一天建成的,如果是个小团队提出的框架,我可能觉得会凉。但是以Spring多少年在Web开发上的积淀,然后能够自我革新提出Webflux,并且打算建立一整套Reacitve生态,我觉得成为主流还是很有可能的。还是拿前端的例子来说,为啥大家十年如一日JQuery用的好好的,然后接受Angularjs的双向绑定,因为首先是Google提出来的,它自己内部就有大量应用。为啥Angularjs用的好好的,突然又开始用React的Virtual DOM?因为首先是Facebook提出来的,它自己有成功的应用。

转载于公众号“程序猿DD”


其他职业越老越值钱,程序员越老越贬值?

科技创新小小鸟a 发表了文章 • 0 个评论 • 44 次浏览 • 2021-04-16 14:47 • 来自相关话题

前言今天一早,看到NBA交易消息中提到:小加索尔与洛杉矶湖人队签下两年老将底薪合同。业界评论一致认为湖人这次在中锋这个位置进行了补强,甚至有人认为湖人是捡了个大便宜。小加索尔作为一个85年出生的球员,在NBA赛场上已经是处于职业生涯晚期的球员,为什么还这么受关... ...查看全部

前言

今天一早,看到NBA交易消息中提到:小加索尔与洛杉矶湖人队签下两年老将底薪合同。业界评论一致认为湖人这次在中锋这个位置进行了补强,甚至有人认为湖人是捡了个大便宜。

小加索尔作为一个85年出生的球员,在NBA赛场上已经是处于职业生涯晚期的球员,为什么还这么受关注呢?其实每年NBA交易期都会有这样类似的情况,一些早已功成名就的老将,不在意薪水的多少,只想加入一只有争冠实力的球队,并且往往他们的经验会让球队受益匪浅,关键时刻往往会帮助球队获得胜利。正如我们华夏民族一直流转的那句“家有一老,如有一宝”。

每一个职业每一个行当,一代代的经验传承,造就了中华民族五千年的文化荟萃,但是现在似乎程序员这个职业有些另类,别的职业都是越老越值钱,唯独程序员,在众人的眼中越老越容易失业?越老越贬值?

那究竟是什么原因造成了这个现象呢?让我们一起看看知友们都是怎么说的吧

做程序员这些年,我一直在思考一个问题,就是:

就互联网公司而言,对于公司好的发展逻辑其实是跟对于个人来说好的发展逻辑似乎是有冲突的。

对于一个大公司来说,一个新员工进来,首先要做的是什么?

学习遵守公司的流程规范,让自己的工作内容和工作方式都以一种标准化的方式进行。

哪怕你做了某个很好用的工具,或者发现了做这件事的更高效的方法。

那么在得到上级认可之后,你要干什么?

把这个东西整理成标准的流程,文档,以提高后面新入职的同事的工作效率。

为的是什么?

为的是哪怕有一天你不在这个公司了,你所做的这一部分工作也能很快地找到另外一个人来代替。

当然,然后还有进行项目开发时对于代码和文档的各种规范和要求,越是大公司,在这方面的要求越是严格。

为的是什么?

为的是哪怕你作为这个项目的核心开发者,但是如果有一天你主动离职了,或者年龄大了被公司裁了,这个项目依旧可以正常地运行迭代下去。

这确实是对于公司发展来说最好的逻辑。

但是问题是,这对我们作为员工的个人来说,可能并不是一个好的逻辑。

如果一个公司想要做大,想要走的远,那么他们就需要通过标准化,规范化的流程来把个人因素变动所带来的的影响降到最低。

而在里面作为的螺丝钉的程序员,除了写代码完成业务功能以外,还要把代码写的尽量让大家都能看懂,让后来人能轻易接手。

但这也为他后续被更年轻,更能996的程序员取而代之,埋下了伏笔。

而在某些传统行业,则不是这样的。

尤其是有些老一辈的手艺人,确实是越老越吃香,甚至是一个匠人到了六七十岁,还有人愿意把自家孩子送到这个匠人门下当学徒,学习手艺。

难道是因为这个行业真的有什么常人难以学会的知识或是技能,哪怕钻研了五六十年,还是有着很大的提升空间。

以至于研究了50年的手艺人,就真的比研究了30年的,要高好几个档次,所以大家才都青睐那个更老的手艺人吗?

也不一定。

也有可能是人家只是有几个压箱底的绝活,但是这个绝活,在这个手艺人临终之前,都不会轻易地交给自己的徒弟,更不要说是新入行的同事了。

毕竟人家是打算靠这点绝活,吃一辈子饭的,如果随随便便就交给徒弟,那师傅不就饿死了吗?

所以说,明白了吗?

为什么有些职业是越老越吃香,而程序员不是越老越吃香?

因为互联网公司的逻辑是:”虽然我需要程序员来帮我开发软件,但是我更需要的是这个软件离了他之后,依然可以好好地运行,所以说我会竭尽全力地来保证流程的规范化,代码的可读性以及业务逻辑的文档化。“

这样一来,即使程序员开发出了某个发展很好的项目,但是在这个项目进入稳定生产之后,也跟他没有太大关系了。

他并不能靠对着某个项目的理解,而吃一辈子饭,因为公司的规范要求他把所有有关这个项目的理解,都整理成文档,模型,和代码注释。

他要么抓住某个机会成为管理层,拿到公司股份,要么不断跟进学习日新月异的新兴技术,要么,就只能等自己老了,精力和体力都比不过年轻人的时候,被更加年轻的程序员所取代。

从这个角度上看,公司和程序更像是一个生命,而前赴后继的程序员们,只是不断往这个生命里面注入动力的干电池而已。


自由飞的想法

大部分的中国企业,就没把程序员当做“脑力劳动者”,而是当做“体力劳动者”在用!

996是福报啊!过了35岁,搬不动砖了,996都没你的份。

我以前看报道,说“中国航天”深化改革啥啥啥的,其中一个成果就是“队伍平均年龄28.6(大概吧,总之很年轻)岁”,然后今年火箭已经炸了三次了。——这事我就随口一说,究竟什么原因炸的,炸得好不好,应该不应该,我不是行内人士,大家不用给我上课,实打实的说,我也不关心。

但以我一个快40的老码农而言,不说别人,就说我自己,我非常肯定确定以及一定:

我的能力从来没有贬值。恰恰相反,随着经验的积累,我的能力与日俱增。

我相信,就算不是全部,但很多老码农都会有这种感觉。

新东西学不动,那是懒得学!工作中用不到的,我学他干嘛?真要学的时候,分分钟捡起来,比你刚入行的菜鸟不知道快多少倍。

而且会倒腾个新技术就算有能力了?呵呵,

除了高质量代码生成以外,还有很多其他需要日积月累的技能,譬如全面审查需求,妥善安排进度,快速bug fix……

但是,企业关心这些么?

不过是搬砖的而已,能把砖搬过去就完事了,还管你怎么搬?

外包单位就不说了,卖出去一个是一个,关键是挣差价,你的工资是成本,当然越低越好。

互联网公司,钱烧得霍霍的,产品急着上线呢!还管你代码质量,只管你能加班不?!屎一样的代码糊上去再说,美其名曰“及时反馈快速迭代”……

软件公司……等等,中国有软件公司么?反正除了屈指可数的那几家,目之所及真能赚钱的都是骗补贴的!

明白了吧,这就是你问的为什么。

老程序员本身没有贬值,所谓贬值,是因为人力市场的需求。

怎么办?凉拌!

唉,希望未来能有更多脚踏实地的、以产品质量取胜的软件公司涌现出来吧!


invalid s的表述

古话说的好:“飞鸟尽,良弓藏;狡兔死,走狗烹”。

不光程序员越老越容易失业,国内一切技术行当不都这样吗?

身为技术人员,在自身职业前景上,必然要遭遇两个问题。

  • 第一个问题是他自己能控制的:你,究竟掌握了多高的技术?

是面向搜索引擎编程、只会CRUD呢;还是能够编写更高质量的代码、解决日常问题?

或者,是有充分的大中型项目设计、实施经验,甚至能够主持有一定难度的项目开发?

或者是,你能否掌握“核心科技”,挑战业界大佬?比如和思科比比网络调度算法、和Linus比比OS开发、写个数据库挑战Oracle、搞个Hadoop挑战yahoo甚至google?

可想而知,当你只会面向搜索引擎编程、只会CRUD时,你当然就是个一次性消耗品。用到三四十岁差不多也该用坏了,找个借口扔掉就是。

比赛“跑不死就往死里跑”的话,你怎么可能比得上二十来岁的小年轻呢?

想要“越老越值钱”,你就不能在年轻人的优势领域停留,你就必须不断提升自己、拓宽眼界、抬高上限——你猜Linus担心不担心失业?你猜yahoo里面编写/维护hadoop的、google里面优化big table page rank map-reduce的,他们担心不担心失业?

你究竟学会了多少,就决定了你的命运。

当你只能拼996007时,你那二十岁的身体还的确能支撑你扛大包;但到了三四十岁,哪怕没有落下一身职业病,你,还能像年轻人那样“昨天摔了一跤整条腿都紫了今天打个绷带照样活蹦乱跳”吗?

所以你失业了。那些挤走你、顶替你的,也会像你一样,在被人超负荷使用十年、落下一身病痛后滚蛋。

这就是第一个问题:你不为将来打算,急功近利透支身体996/007,所以你越老越容易失业。

你不光越老越容易失业,你还会落下一身病痛。三四十的身体甚至比不上那些会保养的、六七十的老人。你不得不掏出大量金钱来维持自己的基本生存。

如果你压根就不是什么“良弓”,凭什么阻止别人把你像垃圾一样踢开?

人无远虑,必有近忧。

  • 技术人员必将遭遇的第二个问题并不是他们能控制的。

那就是:你把自己修炼成了全世界顶尖的超高精度复合弓;但你的国家压根就没有射箭比赛。

是的,你懂操作系统内核;但中国有哪家公司在开发自己的OS?

是的,你懂数据库算法编译器优化;但中国有哪家公司能做数据库能写编译器?

如果整个社会都只能追逐那么几只半死不活的残疾兔子;你,身手矫健又有何用?

人山人海,哪里见得到兔子。

结果你还想吃多点,否则……都不够维持你的一身肌肉。

相信我。用不了多久,你也会饿成一条病恹恹的瘦狗。

那么,这就是国内醉心于技术者面对的窘境:我们压根就没有能插手基础性、支柱性软件项目的公司。唯一会的就是互联网,就是想尽办法薅用户羊毛的终端软件。

对大多所谓的“互联网公司”来说,写这种软件,“面向搜索引擎编程”“调库专家”基本够用。更高的,他们根本不敢想。

正是这种现状,使得一些缺乏眼界者压根不敢想“需要熟练使用链表算法的工作”;相反,他们会告诉你,会调库足矣、照搬互联网上搜到的代码就够用了——甚至还有在我的回答下言之凿凿、说“专家”说了,能搜到现成的代码就千万不要自己写,自己写的质量太差……

但事实是,哪怕在中国,照样有不算太少的中高端职位;这些职位的基本要求就是“不准抄网上代码”。

这是因为写出这些代码的人水平良莠不齐、写的时候也未必是按工业化/商业化标准精益求精(经常就是为了让初学者明白,所以省略了很多很多东西)——对这类中高端职位所要求的、业界top5%、top0.5%、top0.05%的、较为正规的程序员来说,这种东西说好听点叫粗制滥造,说难听点就是垃圾。

当这些人崇拜的“专家”都在顶礼膜拜网上的劣质代码时,他们的水平也就可想而知了。

眼界所限,他们完全不可能知道那些中等以上水平的程序员在做什么;在他们看来,一行代码出一堆错误是必须的——我说自己一口气写几千行不出错,他们就破口大骂:追着骂、单独开贴骂;直白的骂、阴阳怪气的骂……

这种情况,在过去是不可想象的。

在当时,别说垃圾到这种程度了,任何问题只要简单到用搜索引擎搜一搜就能解决,你敢问,就会被老手怼回去。很多论坛把“提问前应该做到什么”置顶;“STFG(Search The Fucking Goolge)”是被人普遍接受的、对小白问题的标准回复。

但现在,连网上苦口婆心的解释都读不懂、只能逐字逐句照搬现成的代码的小白敢“组团围剿”那些敢说自己能写程序的“吹牛者”。

可想而知,这种劣质码农的声音淹没一切时,这个行业会变成什么样子。

别说开拓新的市场、新的疆域了,就连抄,他们都不敢抄热乎的。

这反过来强化了劣质码农们的认知——没错,中国啊,它本来就不需要高于“面向搜索引擎编程”的装B犯。反正你们学了也没用,大家一起996,欢乐的卷起来吧。

业界整体的低水平,使得你除非在校时就憋着一口气、玩命的往世界一流水平赶;否则一旦开始工作,庸人们很快就会把你拖进自己的节奏,然后干净利落的打败——这工作你能做我也能做,我见经理满脸堆笑,你呢?书呆子。什么叫你一周抵我们一年?谁看见了?

中国技术人员地位低,原因就在于此。

一方面,因为对未来的预期过低,因此从一开始就没学到东西,就是一劣质码农;另一方面,行业整体上限不高,绝大多数人还在一门心思的拉低下限。

如此一来,未来哪还有好?

但是,这并不是全部。

事实上,正常的市场竞争下,谁落后,谁死。

因此,报社的程序员可以写出django,车库里的穷小子能折腾出google。

技术是需要积累的。只要学进去了,你的积累就绝不会是无用功。

因此,虽然按比例算,也许99.99的程序员果然是年纪大了就得滚蛋;但这不正是他们为自己做的规划吗?起初就什么都没学到、入职了也只会996没有任何技术积累——美其名曰“你需要掌握的东西,入职一个月内就能学到”。

呵呵,真这么简单全世界的大学都在坑钱不成?一个月就能学完的东西,非要把你拘禁起来教上本科四年硕士两年博士N年都还不让毕业?

你把自己当一次性用品培养,就别怪别人用旧了把你一脚踢开。

相反,那些真正知道四年本科要教你什么、知道你和世界先进水平还有多大差距的人,他们会抓住一切机会,不间断的前进,前进,继续前进。

我大一就自学到了中断服务程序、可以直接写端口命令字绕开OS/BIOS直接控制硬件;也知道动画、音频、视频、3D图形等等的基本原理;当时同学间流行一个打字游戏,但我觉得那个东西写的不好,于是花了一周不到就写了个更好的。

因此,我可以毫不含糊的吐槽——绝大多数本科生,四年连个大一水平都没学到。

比我强的车载斗量。

那么,本科四年我都甩开某些人四年,之后工作了,盯着那些比我强的紧赶慢赶,都不过勉强维持个“看得到别人尾灯”的局面;那么,一毕业就比我慢了四年、还以为一个月就学会了一生所需的全部知识的他们,有可能看见我车尾的扬尘吗?

不光我不担心自己学的东西没人要;那些比我强的没边的,照样不担心自己学的东西没人要。

甚至可以说,越是不顾那些庸人的眼光、我行我素学的精深的,越是不怕失业。因为人家的就业市场是全世界。

不是程序员这个职业越老越不值钱,而是现在的程序员处于工业革命早期煤矿工人所处的境地。

新的世界刚出现一个雏形,现在的程序员只是在用自己的血肉去充当地基和铁轨,铸造锅炉并充当点燃第一把火的燃料。

表面上看起来相对农民阶级(传统制造业),工业革命初期的产业工人收入待遇提高了很多,但是那是以压缩劳动寿命来实现的。

他们确实代表着先进生产力的发展方向(并且就像煤炭行业至今仍然是采矿和机械制造业最先进技术的集中展示平台一样),但是悲哀的是,他们自身却不是先进生产力。

作为程序员的你,这些一直接触的词都念对了吗?

科技创新小小鸟a 发表了文章 • 0 个评论 • 41 次浏览 • 2021-04-16 14:47 • 来自相关话题

很多时候,大家可能都觉得程序员英文一定很好。因为我们每天都对着满屏幕的英文,噼里啪啦一整天。讨论个需求,还是不是冒几个单词,产品MM和运营JJ们,心理几万头曹尼玛奔过:能不能讲人话!很多时候,我们自信满满的说出一个又一个高大上的操作名、技术名,看似装逼成功!但... ...查看全部

很多时候,大家可能都觉得程序员英文一定很好。因为我们每天都对着满屏幕的英文,噼里啪啦一整天。讨论个需求,还是不是冒几个单词,产品MM和运营JJ们,心理几万头曹尼玛奔过:能不能讲人话!

很多时候,我们自信满满的说出一个又一个高大上的操作名、技术名,看似装逼成功!但是我们都说对了吗?

下面,我们一起来重现一下这些场景,看看你都对了几个?

第一轮

单词一:Archive

Archive:档案、归档。常见于一些管理类需求或是运维相关日常。

正确发音:

  • 英:[ˈɑːkaɪv]

  • 美:[ˈɑːrkaɪv]

单词二:Digest

Digest:字面意思为摘要、汇编。常见于一些数字证书、认证算法相关的内容中。比如:HTTP的认证方式中有一种就叫Digest认证,是Basic认证的升级版。

正确发音:

  • 英:[daɪˈdʒest , ˈdaɪdʒest]

  • 美:[daɪˈdʒest , ˈdaɪdʒest]

第二轮

单词三:Adobe

Adobe:一家专注于图形设计、影像编辑与网络开发的著名软件公司。PhotoShop、Illustrator、Dreamweaver等设计类著名软件均为它们开发。如果您对设计师MM感兴趣?那么千万别再念错了!

正确发音:

  • 英:[əˈdəʊbi]

  • 美:[əˈdoʊbi]


单词四:Cache

Cache:缓存。不论在讨论硬件领域还是软件领域,前端还是后端技术时候,当碰到性能相关难题的时候,经常出现的一个词。你念对了吗?

正确发音:

  • 英:[kæʃ]

  • 美:[kæʃ]

第三轮

单词五:Apache

Apache:一款应用服务的名称,也是Java领域一个重要开源基金会的名称。近几年有好几个国内开源项目也都加入了Apache基金会,比如:我们所熟知的Dubbo、Skywalking!

正确发音:

  • 英:[əˈpætʃi] 

  • 美:[əˈpætʃi]

单词六:Suite

Suite:套件。比较常见于测试小组中,比如:Test Suite,意为测试套件、测试集合,代表已一组Test Case(测试用例)。

正确发音:

  • 英:[ˈɑːkaɪv]

  • 美:[ˈɑːrkaɪv]

转载于公众号“程序猿DD”