华为Mate80央视直播:一场技术与舆论的双重战役

背景 2025年11月25日,华为正式发布了Mate80系列手机。这场发布会选择在央视直播,这一决策本身就值得玩味。作为中国科技企业的代表,华为的每一次大动作都不再仅仅是商业行为,而是承载了更多的象征意义。 Mate80系列概览 根据公开信息,Mate80系列共推出四款机型: Mate80 标准版 - 入门旗舰定位 Mate80 Pro - 主力高端机型 Mate80 Pro Max - 大屏旗舰 Mate80 非凡大师版 - 顶配奢华定位 全系搭载纯血鸿蒙系统(HarmonyOS),这意味着华为彻底切断了与安卓生态的依赖关系。 央视直播的战略考量 为什么是央视? 一家商业公司的产品发布会登上国家级媒体平台,这在中国科技史上并不常见。华为此举至少有三层考量: 政治背书 - 在中美科技博弈的背景下,央视直播本身就是一种态度表态 市场覆盖 - 央视的受众远超科技圈,有助于触达更广泛的消费群体 品牌塑造 - 将产品发布上升为"国家大事"级别,强化民族品牌形象 利弊分析 优势: 极大提升品牌公信力 获得主流舆论支持 在下沉市场建立认知优势 风险: 过度绑定可能导致国际市场顾虑加深 商业行为政治化可能引发部分消费者反感 央视受众与高端手机目标用户存在错位 纯血鸿蒙:技术自主的最后拼图 Mate80系列最大的技术亮点不是硬件,而是全系预装纯血鸿蒙系统。 技术层面的挑战 纯血鸿蒙意味着: 应用生态重构 - 开发者需要适配全新系统 兼容性阵痛 - 早期用户体验可能面临应用缺失 性能优化 - 新系统需要时间打磨 根据华为官方数据,鸿蒙生态已有超过10万个原生应用。但与安卓、iOS数百万级别的生态相比,差距依然明显。 自主可控的代价 技术自主从来不是免费的午餐。华为在芯片、操作系统、应用生态三个层面同时推进自主化,这种"全栈自研"策略在全球科技企业中极为罕见。 其代价是: 研发成本激增 - 每年千亿级别的投入 生态建设周期长 - 至少需要3-5年才能成熟 用户体验阵痛 - 早期用户承担了生态建设的成本 客观评价 产品力 从已知参数来看,Mate80系列在硬件层面依然是第一梯队: ...

2026年2月20日 · 1 分钟

豆包AI编程初体验,惊人的生产力工具

假期有闲暇学习一下AI相关的知识,尝试着想用公众号对接DeepSeek做一个问答,当做一个BlogAgent,又不想写太多的工程类的代码,想着AI这么强大,能不能直接用AI生成代码。没有看阿里,百度的产品,直接试用了豆包的AI编程,通过这两天的试用,AI惊人的生产力着实让我惊掉下巴。 一、项目级代码生成 我一开始描述,要求 实现一个微信公众号的后台服务代码,可以接收用户信息,并且回复。 豆包直接生成了一个Python的代码,实现了微信公众号的后台接口,并且实现了签名认证,并且给出了详细的代码说明和注意事项。 然后我又要求使用Java+Spring Boot实现,它竟然给我实现了了一个完整的Maven项目。代码下载下来是真的可以跑的。 二、根据要求重构代码 在仔细看了下整个工程,代码就是一个Spring Boot的启动类,再加一个Controller。稍显不足的是,关于签名的代码,放在了Controller里,导致代码很乱。我随即发了一个优化建议: 把WechatController里的通用公共代码抽出去 这货竟然完全听懂了,乖乖的提取了一个Utils类,把签证签名,XML解析等相关的操作放了进去。 我又对比了下微信的API文档,我疑问道: POST接口不需要验证签名吗? 它竟然立马意识到自己的错误,修正了自己的错误: 三、根据要求增添内容 我继续下达着我的命令: >请生成Spring Boot的配置文件 >再加入log4j2的日志框架,把相关的异常打到日志里 >把参数搞成对象,把解析xml改成通用的反序列化拦截器 >响应体也可以搞成对象,使用序列化拦截器 >把token改成配置项形式,放在配置文件里 >使用langchain4j集成调用deepseek。当微信用户发来消息以后,转发给deepseek,然后把响应给微信用户 >Spring Boot的方式初始化langchain4j 并且把相关代码抽出去单独的类,整个项目包名改成com.zhaoyanblog.agent项目名称微blog-agent >帮我在pom里设置国内的maven仓镜像地址 >集成对wordpress的访问,当微信用户请求“wp:” 开头的信息时,搜索WordPress里的文章,返回给用户。 >微信返回的消息 要是一个包含文章的摘要富媒体链接,业务点击消息可以跳转到网站。WordPress的网站地址zhaoyanblog.com。要放在配置文件里。 关于微信的Token也放在额外的类里,不要放在controller里 >请对工程使用Spring boot的方式配置accesslog, >配置文件里的注释在IDEA里是乱码,请修正. …… 它就像一个不知疲倦的程序员,不断的实现着产品经理提出的需求 四、帮我修正Bug 有关freemarker模版的问题,开始我希望把markdown改成HTML。它一开始给我的代码其中有这样一段: <p class="text-gray-800"><span class="speaker-highlight">DeepSeek</span>:<#noescape>${conversation.getContentAsHtml()}</#noescape></p> 但是我真实跑起来的时候,它报这样的错误 #noescape with no matching #escape encountered 它直接给我了解决方案,并解释了原因: <span class="speaker-highlight">DeepSeek</span>:${conversation.getContentAsHtml()?no_esc}</p> 但是好像还不行,我直接把报错信息再贴给它 ?no_esc can't be used here, as the current output format isn't a markup (escaping) format: undefined(mimeType=null, class=f.c.UndefinedOutputFormat) 这次它给的答案,完美解决了问题: 五、竟然提示我遵守规范 ...

2025年5月3日 · 1 分钟

本小站正式从阿里云迁往华为云

本站在阿里云ECS已经有5年之久了,1C2G的配置,1M带宽 外加20G云盘,一年要耗费1100多大洋~~。随着云化技术的发展,一直等着阿里能有优惠,然而一直都如此。 碰巧前段时间看到华为云的优惠活动。新注册用户 2C4G的HECS 3年只要700多。瞬间心动,直接买了。 前段时间增加了域名备案,但是一直没有机会把主机迁移。 今晚早下班,一并做了迁移。同时把好久没升级的nginx和php都升级到了最新版本 华为云 棒棒的^_^

2020年7月17日 · 1 分钟

Spring源码阅读(一):Spring是如何扫描某个包下面所有的类

Spring扫描注解的功能 我们知道在Spring中可以使用注解声明Bean,可以让我们不用再去配置繁琐的xml文件,确实让我们的开发简便不少。只要在Spring xml里配置如下,就开启了这项功能。 <context:component-scan base-package="com.zhaoyanblog" /> Spring就会自动扫描该包下面所有打了Spring注解的类,帮你初始化病注册到Spring容器中。 @Service public class UserController { ​ @Autowired private UserDao userDao; ​ //TODO } 上述行为,就和在xml里进行下面的配置是等价的。 <bean class="com.zhaoyanblog.UserController"> <property name="userDao" ref="userDao" /> </bean> 那么问题来了,Spring是怎么扫描到com.zhaoyanblog包下面的所有带注解的类的呢? context:component-scan标签的处理者 要弄清楚为什么在xml里配置了context:component-scan就可以实现这样的功能,就要现找到这个标签的处理者。我们很容易联想到Spring解析xml的基本原理,就是遇到这个标签以后,交给一个类处理,这个类扫描包下带注解的类,初始化成对象。我们就是要找到这个关键的类。 Spring对Xml的解析功能后面阅读,这里先简要描述。Spring的jar包里有两个重要的配置文件:spring.schemas和spring.handlers,在META-INF目录下。 spring.schemas记录了xml的每个命名空间,对应的Schema校验XSD文件在哪个目录。 http\://www.springframework.org/schema/context/spring-context-4.2.xsd=org/springframework/context/config/spring-context.xsd http\://www.springframework.org/schema/context/spring-context-4.3.xsd=org/springframework/context/config/spring-context.xsd http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context.xsd spring.handlers里配置了每个命名空间的标签都由哪个类处理 http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler 我们可以看到context这个命名空间由org.springframework.context.config.ContextNamespaceHandler这个类处理。打开这个类 public class ContextNamespaceHandler extends NamespaceHandlerSupport { ​ @Override public void init() { registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); } ​ } 这个类为每个标签都给出了一个处理类,component-scan的处理类是ComponentScanBeanDefinitionParser 继续打开ComponentScanBeanDefinitionParser private static final String BASE_PACKAGE_ATTRIBUTE = "base-package"; public BeanDefinition parse(Element element, ParserContext parserContext) { String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); ​ // Actually scan for bean definitions and register them. ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages); registerComponents(parserContext.getReaderContext(), beanDefinitions, element); ​ return null; } 看到这里整明白了,扫描某个包下面的所有类的工作,就是ClassPathBeanDefinitionScanner干的。入口是doScan方法。 查找所有的包路径 ClassPathBeanDefinitionScanner有很多细节,比如可以设置class的filter, 设置classloader等等,我们先关注最主要的功能,就是怎么找到一个包下面所有的类的。 通过调用关系,一路找下去 doScan->findCandidateComponents(super)->scanCandidateComponents(super) private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); 我们发现,原来Spring是在classpath下面,通过查找所有classpath*:com/zhaoyanblog/**/*.class的文件来实现的啊。 ...

2020年3月24日 · 3 分钟

强烈推荐阿里云镜像站

阿里巴巴构建的阿里云开发者社区真是懂程序员所想,这里有一切你想你要的。 主页: https://developer.aliyun.com 特别是它的阿里云镜像站,真是一个大宝藏啊 https://developer.aliyun.com/mirror/ 里面包含所有Linux版本的操作系统镜像 此外还有: DNS解析 https://developer.aliyun.com/mirror/DNS NTP服务器 https://developer.aliyun.com/mirror/NTP 各种语言的镜像: python pypi软件仓 https://developer.aliyun.com/mirror/pypi rubygems https://developer.aliyun.com/mirror/rubygems maven仓镜像 https://maven.aliyun.com/mvn/view npmjs https://developer.aliyun.com/mirror/NPM

2020年3月8日 · 1 分钟

从苹果发布会看华为的创新地位

北京时间2019年9月11日凌晨1点,苹果秋季发布会在乔布斯大剧院如期举行,发布了最新款手机 iphone11系列。 iphone11系列能拿得出手提升主要有两个: 一是后置1200万三摄,兼顾广角和长焦,4倍光学变焦,增强夜间模式。二是最新7nm仿生芯片A13,集成85亿个晶体管,提升AI计算能力。注意不支持5G! 此外媒体还总结了6大卖点,除上面两点还包括:电池更大,18W快充,全新配色,售价更便宜。 通过苹果的发布会,我们可以看到目前全球手机厂商的创新点主要聚焦在三个方面:拍照、芯片、AI计算。 而横向比较,我们看一下华为。 首先华为是手机多摄像头方案的鼻祖,华为每款最新旗舰机手机发布拍照能力都会霸榜DxOMark。最新mate30在拍照能力上让人充满期待。 从16nm的950,到7nm的990,华为已经站在了CPU制程的最前沿。麒麟990芯片是世界上首款支持5G双模的7nm终端芯片,集成首次超100亿晶体管。将会用在随后发布的Mate30系列上。这次苹果发布会第一次吧麒麟芯片作为对比对象。但是却拿的华为上一代产品麒麟980. AI方面华为是最先提出NPU的概念,到990已经是好几代了。 我们发现不知不觉华为已经站在了手机创新的前列甚至于制高点上。苹果已经不在是创新的代名词。有人评论这可能是苹果最后一次享受乔布斯的遗产红利,通过简单修改一下参数就可以卖的很好。 最后让我们拭目以待华为9.19 最新Mate30系列全球发布会。

2019年9月12日 · 1 分钟

大岩评“小米自研30W无线闪充”

小米9月9日发布了全球首款30W无线闪充,然后小米高管微博开始宣传造势。 然而有网友质疑小米30W无线闪充使用了和华为相同的供应商IDT的技术方案。 时隔三日,9月12日小米产品总监王腾Thomas长篇回应质疑。 大肆宣传快充最开始有OV发起的,“充电五分钟通话两小时” 广告狂轰乱炸确实带起了OV销量。 前段时间荣耀发布荣耀9X用了10W充电,小米高管卢伟冰带了一波节奏,我想小米可能想趁热继续在充电上冲一冲,给粉丝一个小米有技术的印象。 但是我们分析这篇王腾的回复博文,看到的不是小米对技术的自信,而是心虚和掩饰。看到这5条创新技术,我感受到是小米的绞尽脑汁,勉强无力。 且看其中包括充电策略,保护算法这不是一个手机充电必须有的吗? 安全加密机制算法,我都有点乱了,这里是说加密算法,还是加密的机制?有这样称呼的吗?这个自研的算法安全吗? 可以想象小米是费了多大的劲才挑选出这样的让读者感觉表面有点技术含量的词语啊。 然而最最核心的无线充电芯片,也被加上了“供应商根据小米的需求和电路架构为小米设计”的修饰语。 我的结论是: 雷军一直说自己是科技节的无印良品,追求颜值和性价比。但是手机是一个高科技产业,手机厂商竞争进入了白日化阶段,没有核心技术的厂商会逐渐被淘汰和边缘化。 小米的底牌可能真的不多了。俗话说穷则思变,小米是时候需要把更多精力放在科技创新,打造更多核心竞争力上,而不是高管集体在微博上面耍嘴皮子。

2019年9月12日 · 1 分钟

大岩评“卢十瓦”事件

2019年7月23日,荣耀在西安发布了荣耀X系列的下一代产品荣耀9X系列。4800像素三射,升降摄像头,PC液冷,4000mA大电池,前置指纹识别。同时搭载7nm制程的麒麟810芯片,拥有方舟编译器、EROFS超级文件系统、GPU Turbo 3.0、麒麟Gaming+技术、AI视频防抖,AI智慧通信2.0等多项华为自研高科技。 然而它有一项不尽人意的地方,就是充电仅支持5V2A=10W功率充电器。 小米副总裁卢伟冰抓住这一点不放,在微博上连续多天发文提及此事: 7月23日:“今天友商的产品让人费解,请教: 1.手机支持18W快充,inbox充电器不支持2.手机和充电器都不支持,是哪个?请大家指教” 7月24日:“今天的手机竞争,产品一定要有自己的特色和长板,而且一定不能有短板,尤其是用户非常关注的处理器、拍照、电池、快充、外观材质等,绝对不能偷工减料。卖2399元的手机只支持10W充电,在Redmi团队的话产品经理肯定被开!” 7月25日:“炮制虽繁,必不敢省人工,品味虽贵,必不敢减物力 ”7月26日: “按照友商的理论,我不用做任何测试,先下个结论:充电能力,10W的友商9X/9XPro,一定远落后于18W的小金刚Pro。因为这个世界真的是有“科学常识”存在。世界最顶级的专家,也不可能把10W优化出18W的快充能力。” 7月27日:“五年前的红米Note第一代,就已经是10W充电了…所以最近有点恍惚,好像回到了几年前。但,永远相信美好的事情即将发生” 7月28日:“Redmi 7A是我们高品质的入门款手机,4000mah大电池,售价只要549元,同样标配10W充电。我在想,下一代还要不要继续用10W呢?” 为了把事情彻底闹大 7月29日: “Redmi全民快充计划,划重点: 1.价值29.9元的18W充电器小米商城1元闪购 2.Note7 6+64版本闪降200元仅1199并加送18W充电器。 明天上午10.08分开售,全民进入18W快充时代,告别10W!” 于是网友送了一个外号 叫 “卢十瓦”, 并且产生一个功率单位1卢=10W 卢伟冰在最新的微博里也自嘲“最近不少网友叫我“卢十瓦”,我觉得这其实是件好事,因为这一定会促进产业的共同进步,能给用户带来更好的体验,我预测友商的下一代产品也不会再用10W充电了。想做出好产品就一定要较真!”, 以行业良心自居,和网友打的是热火朝天。这就是“卢十瓦”事件的背景。 我想从另外一个角度分析这个问题:荣耀9X用10W就是偷工减料吗? 荣耀没有技术水平让荣耀9X用上更大功率的快充吗? 显然不是,我想打个比喻:有一天马云骑着自行车锻炼身体,一位开着马自达的上班族看到了,嘲笑马云没有开上马自达。 马云是开不起马自达吗? 但是此时此刻马云他就是需要骑自行车。 荣耀千元机直接上7nm对小米来说就是致命性的降维打击。10W充电就是故意卖个破绽给你。小米体会不到自己的危机,反而操弄起自己熟悉的社会营销。 试想小米任何一款手机,其它任何手机厂商是不是立马就可以造出来? 华为的手机,小米可以造出来吗? 甚至于OV厂手机的一两个特性,小米都搞不出来。没有核心关键技术的企业是不可持续的,也许这就是为什么在资本市场,小米盈利能力不错,仍然被看衰,股票一跌再跌的原因吧。 通过荣耀9X,“卢十瓦”事件,表面看到的是小米的接地气,性价比。更深层次看到的是小米的未来危机,没有核心关键技术,深陷社会营销的小米到底还能走多远?

2019年8月28日 · 1 分钟

Junit单元测试碰到静态变量如何处理

写单元测试用例,是程序员的好习惯,写java程序,一般使用Junit写单元测试。 我在写单元测试用例到时候,遇到一个问题:Junit在整个project中是一个java进程,如果你的程序里涉及静态变量,就会导致两个单元测试类之间相互影响。 你可以每次beforeClass初始化静态变量,但是有时候依赖了很多开源软件,你都不知道究竟一个测试流程里用到了哪些静态变量,甚至不知道如何还原它们。 最有效直接的办法就是每个测试用例都使用一个独立的classloader,也就是说每个test case都是类隔离的。 参考https://stackoverflow.com/questions/42102/using-different-classloaders-for-different-junit-tests 这篇帖子里的回复。实现了这个功能。 具体源码: https://github.com/johnyannj/junit-alone 用法如下: maven引入依赖 <dependency> <groupId>com.zhaoyanblog</groupId> <artifactId>junit-alone</artifactId> <version>1.0.1-SNAPSHOT</version> </dependency> 在你的测试用例中,用AloneRunner代替你原来真实的Runner,并把你真实的Runner,设置给@AloneWith @RunWith(AloneRunner.class) @AloneWith(JUnit4.class) public class JunitAloneTest { @Test public void test() { StaticClass.staticNum++; Assert.assertEquals(1, StaticClass.staticNum); } } 这样你的测试用例就会使用一个独立的classloader来执行了, 试试看吧。

2019年4月28日 · 1 分钟

从大嘴Mate20发布会后采访看雷军三大败笔

10月26日,在mate 20系列发布会之后,余承东接受媒体采访,有人问到mate 20系列的Dxomark评分,大嘴回复“因为P20Pro已经拿下了第一,华为不愿意看到榜单上都是华为手机,想给友商留位置。”在这里我想到了雷军,我认为雷军在类似事情上有三大败笔。 第一: 收购安兔兔 小米创业之初的口号是“为发烧而生”,主打的是性价比,怎么体现手机的性能呢?那就是跑分,有段时间雷军是把“不服跑个分”挂在嘴上的。安兔兔是跑分软件中比较出名的一个,小米也一直占据安兔兔榜首的位置,本来是个米粉们骄傲的事情。然而雷军把它收购了(눈_눈),彻底毁掉了安兔兔的江湖地位,没有人在看重评分,这也毁掉了小米一个炫耀的资本。老罗曾在和王自如的辩论中透露: 有人曾经撺掇他收购另外一个评分软件鲁大师,老罗没答应。看来老罗在某些方面还是比雷军有原则啊。 第二: 投资王自如 国内手机评测做的比较有规模的,王自如的zealer是一个,一部手机有哪些优点和缺点,这些评测视频里的观点很重要,会引导部分消费者的购买选择。老罗也看重了这一点,手机还没发布,就花钱让王自如做评测,提意见。王自如后面不地道的做法就不说了。老罗在辩论里透露了一个信息“小米投资了王自如”。王自如的zealer的独立第三方的身份遭到质疑,这几年都没翻过身来,只能低调做视频。 第三: 合伙潘九堂 手机好不好,还有一个宣传是渠道就是大v推荐,有时候一款手机发布前,手机厂商都会送一些手机给这些大v明星试用,大v们发个点评的微博,也能给手机带来很多人气。潘九堂就是一位,挂名“华强北电子行业研究所分析师”类似职位,活跃于微博,发表一些“独到”见解。他要推荐个手机,还是有人认的。然后就在某一天,潘九堂摇身一变,变成了“小米产业投资部合伙人”,专门给小米赚起了吆喝。 雷军的这些行为就像评委是选手的一大妈,监工是包工头的二姨夫,做的太明显,也太蠢,败笔~

2018年11月13日 · 1 分钟

基于SCRAM-SHA256实现的Cassandra安全认证插件

Cassandra提供认证机制,保证访问安全,但是默认的PasswordAuthenticator是简单的用户名密码认证,客户端在连接后传输用户名密码,服务器确认有效即认证通过。但是在认证的过程中直接传输的是明文密码,有被抓包泄漏的风险。 Cassandra服务端和JAVA客户端本身都支持SASL扩展 https://tools.ietf.org/html/rfc4422 SCRAM-SHA256是SASL的一种实现方式,参考 https://wiki.tools.ietf.org/html/rfc5802 https://tools.ietf.org/html/rfc7677 使用SCRAM-SHA256认证,仅通过抓包是无法破解密码的。 基于SCRAM-SHA256标准,我实现了一个cassandra的插件,放在了github上 https://github.com/johnyannj/cassandra-secure-plugin 欢迎使用

2018年10月14日 · 1 分钟

赵岩的博客全站HTTPS改造

互联网安全和个人隐私越来越被人们关注,不仅仅是电商等交易网站都实现了全站https,现在微博、百度以及大大小小的博客都实现了全站https。如果你的网站不是https的,火狐、chrome、IE浏览器都会在地址栏前方提示用户 你当前访问的网站是不安全的。 为了跟风,赵岩的博客今天起全站使用https。 为了实现全站HTTPS。我主要做了以下工作: 第一、HTTPS证书 https使用SSL传输协议,SSL之所以安全,是因为加密传输的。初始公钥由服务器传递给浏览器,为了保证公钥安全的传输到浏览器,并被浏览器认可,我们需要一个由第三方权威机构签名的证书。详细参考《HTTPS到底是如何保证通信安全的》 普通的单域名证书一年需要1000多元,我们自然不会去花这个钱的。阿里云代理的赛门铁克提供个人免费域名证书。可以直接申请。阿里证书申请 申请的时候选择“Symantec ”、“免费型”、“一个域名”。阿里云会要求DNS或者文件验证,证明你是域名的拥有者。整个申请过程10几分钟可完成。 第二、升级Nginx Nginx需要使用–with-http_ssl_module参数编译,确保支持https。为此我趁机会升级了下Nginx的版本到最新版本。 把你的证书pem文件和私钥key文件上传到服务器。 配置nginx.conf,监听443端口并加载证书。 原来监听的80端口,301转向443端口 server { listen 80; server_name zhaoyanblog.com; include black_list; rewrite ^(.*) https://$server_name$1 permanent; } server { listen 443; server_name zhaoyanblog.com; ssl on; ssl_certificate cert/xxx.pem; ssl_certificate_key cert/xxxx.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ...... 第三、全站HTTPS 1、检查网站内有没有引用了别的网站的js。需要切成https地址。或者根据document.location.protocol自适应当前的访问协议。 比如:微博、百度统计、百度站长、百度联盟广告等等组件。 http://widget.weibo.com/weiboshow/index.php 改成 https://widget.weibo.com/weiboshow/index.php 2、检查是否直接使用了本站的http地址。改成相对路径。虽然已经配置了80端口301跳转。这样改会少一步对服务器的访问。 比如:/wp-content/uploads/2017/04/zhaoyanblog_2017-04-17_14-50-20.jpg 改成 /wp-content/uploads/2017/04/zhaoyanblog_2017-04-17_14-50-20.jpg 可以通过查看浏览器的调试信息,知道哪些访问的资源仍然是http的。 第四、通知百度进行HTTPS验证 在验证好全站已经使用https,并且访问http也可以301跳转到https。我们需要通知百度等搜索引擎进行https验证。因为搜索引擎在之前都是缓存我们的http地址。需要告知他我们切到https。避免导致收录的页面丢失。 直接登录百度站长,里面有个https验证页面,点击验证即可。 至此赵岩的博客已经实现全站https ...

2018年5月20日 · 1 分钟

关于level压缩策略的level0问题

Cassandra一开始是要写commitlog,当commitlog写到一定大小就会刷到一个sstable文件,再加上对于cassandra,删除也是一种写,这样下去sstable文件会越来越多。必须有一种机制来合并这些文件,并删除墓碑(标记为删除的记录),这种机制叫做compaction,先翻译为压缩。既然要合并文件,就要有合并策略。cassandra一开始只有size模式的压缩策略。后来增加了level压缩。 level压缩提高了读的性能,但是level压缩相比较size压缩更慢,因为它是要保证每个level都有一定数量的文件,新产生的文件都是level 0的状态,同时在执行的压缩任务是有限制的,当几个高level的文件在压缩的时候,可能导致level0的文件堆积。 level压缩需要保证低级别的level的文件较少,是为了提高查询的效率。 为了避免level0的文件因为大量写入而得不到压缩。cassandra采取了一种策略,就是level 0文件数目超过一定限制(默认32),就在level 0采用size压缩,通过合并快速减少 level 0文件数量,同时暂停高level的文件压缩。 这个设计在正常情况下是有好处的。但是当我们扩容一个节点的时候,新增节点的文件全部在level 0。 sstable level 12222 0 0 0 0 0 0 0 那么cassandra会的持续进行level 0的 size压缩。直到level 0的文件减少到32以下 sstable level 32 0 0 0 0 0 0 0 这样你会发现新扩节点会一开始产生一个超大文件,然后再拆分成个个小文件的现象。 问题是:如果你有6个500G的磁盘,而你的单节点数据是2T,那么你的节点会因为空间不足而挂掉。 解决这个问题有两种方法: 一种是磁盘做raid,搞成一个大磁盘。 一种是临时关闭level 0的size压缩,这又是cassandra的一个隐藏技能,在cassandra官方文档里你不会找到。就是启动的时候加禁用level 0 使用 size压缩的参数: ./cassandra -Dcassandra.disable_stcs_in_l0=true 注意这个参数从cassandra 2.0.10以后的版本才有。当解决了问题后建议把该参数还原。因为在 level 0采用size压缩,对于突发写入大量的数据的情况还是有好处的。 参考 https://issues-test.apache.org/jira/browse/CASSANDRA-6621

2018年5月6日 · 1 分钟

Cassandra压缩任务堆积如何处理?

当短时间内写入的数据太多,或者连续扩容多个节点,都有可能导致压缩任务堆积,压缩任务堆积会导致sstable太多,让该节点查询变慢,时延变大,一直累积下去,集群会变的很不稳定。解决方法如下: 加大压缩速度阈值 默认压缩阈值是16Mb/s,偏小,可以更改的大一点,这个参数是可以通过nodetool setcompactionthroughput xx进行修改,配置文件cassandra.yaml里的默认值(配置项是compaction_throughput_mb_per_sec),也建议修改到一个合适的值,否则某一天重启节点,又恢复到了默认值。 增加压缩线程 修改配置文件cassandra.yaml里的配置项concurrent_compactors,这个不能动态调整,需要重启生效,默认是2-8之间的一个值,取自数据盘和cpu个数的最小值,这个值一般不需要动,除非你是ssd的盘,可以适当的增加。 临时关闭gossip 如果只是其中一个节点压缩堆积,负载特别高,可以考虑先临时关闭这个节点的gossip,使用nodetool disablegossip命令。这样这个节点对于客户端而言就是DOWN的状态,客户端就不会发请求到该节点,但是集群内部之间通信正常,不会丢失数据。只要你不使用All一致性,是不会影响业务正常请求的。然后你可以把节点的压缩速度阈值调为0,也就是不限制速度,让它早点压缩完毕恢复正常。最后记得用enablegossip恢复。 临时忽略墓碑 这个方法不在cassandra的官方文档里,也没有出现在官方的changelist里。因为这是一个很危险的操作,墓碑不及时清除,会带来读操作性能问题。如果你确认短时间内不清除墓碑不会对你的业务场景产生影响,你可以尝试临时使用该方式,在压缩完成后恢复,不能长期使用。 cassandra在压缩的时候为了安全清除墓碑,会查找多个sstable文件,当压缩堆积,sstable很多的时候,压缩会变的相当缓慢。所以官方增加了这么一个彩蛋形式的配置项。这个配置项是一个环境变量,在启动的时候指定 ./cassandra -Dcassandra.never_purge_tombstones=true 注意这个配置项在2.1.15版本以后才有。

2018年3月7日 · 1 分钟

关于Cassandra的分段Repair

为什么要Repair Repair对Cassandra集群是极为重要的,因为频繁的数据删除以及机器Down掉(尽管有Hinted Handoff机制)都会可能导致数据不一致(多个副本之间)。在Cassandra日常维护中,我们要例行对集群进行Repair操作,使用nodetool的Repair命令。 Repair原理 Cassandra在Repair的操作分两个步骤: 第一: 创建Merkle tree Merkle tree是一个二叉树,二叉树最底层是要比较的数据块的hash值,父节点是两个子节点的hash值(=hash(hash1+hash2))。二叉树的高度是15,也就是说最底层有2^15=32768个叶子节点,对应有32768个数据块,如下图所示。 计算Merkle Tree的过程需要依赖磁盘IO。为了不影响业务,你可以限制压缩阈值(nodetool setcompactionthroughput),因为这个过程被称作validation compaction,体现在压缩任务里。 第二:比较Merkle Tree,找出差异进行数据传输。 为每个副本创建Merkle Tree以后,副本之间只要通过比较最顶端的hash是否一致,然后一层层比较下来,就可以找到不一致的那个数据库,然后进行数据传输进行修复即可。 合理分段Repair 上面的修复过程有个问题,就是Merkle Tree是存储在内存里的,所以Cassandra对高度进行了限制,只能有15层,数据只能分为32768数据块。那么这就限制了Merkle Tree的精度,假设一个节点有10万个分区key,每个数据块大约有30个,假设其中有1条数据不一致,那至少要传输30个分区key的数据。这是很浪费集群带宽和修复时间的(修复需要在gc_grace_seconds周期内完成,防止删掉的数据又出现) Cassandra的nodetool repair提供了分段Repair的参数,-st -et分别表示token段的范围,假设我们每次repair的数据正好有32768个分区key,那么我们就可以进行精确的修复,减少不必要的传输。当我们把所有的token小段repair完毕,就相当与我们把所有数据进行了repair。 那么问题来了,怎么样对token段进行细分呢? 每个cassandra节点都有个表叫 system.size_estimates(好像是从2.1.4版本开始),在里面记录了每个表在每个token段上大约有多少分区key(partitions_count)以及每个分区key的大小(mean_partition_size) CREATE TABLE system.size_estimates ( keyspace_name text, table_name text, range_start text, range_end text, mean_partition_size bigint, partitions_count bigint, PRIMARY KEY (keyspace_name, table_name, range_start, range_end) ) 你可以遍历所有的token段进行repair,遇到分区key较多的token段(大于32768),继续细分成多个子token段进行repair。

2018年2月25日 · 1 分钟