
AWS Lambda 允许设置
Debugging and error handling, 在 Lambda 出现异常,达到最大的重试次数后,把以下信息放到选择的 SNS 或 SQS 主题作为死信队列(DLQ - Dead Letter Queue),包括- 原始 Lambda 接收到的消息(基于 SNS 和 SQS 消息的总大小,可能会被截取,本人猜测,尤其是 Kinesis 的消息会比较大)
- 原始 Lambda 的 RequestId
- ErrorCode(三位数字的 HTTP 错误码)
- ErrorMessage, 即原 Lambda 抛出 Exception 的 getMessage() 信息,截取 1 KB 字符串
并且 Lambda 要使用 DLQ 的话还必须设置当前 Lambda 的 IAM role 有对于 SNS/SQS 主题相应的
sns:Publish和sqs:SendMessage权限。AWS Lambda 基本重试规则:对于 Kinesis 消息会无限重试直至消息过期,对于 SNS 或 SQS 的消息出现异常后会再重试两次。参考:AWS Lambda Retry Behavior。
而在重试次数用完后仍然失败,并且设置了 DLQ 的话就会发送消息到 DLQ 中去。 Read More
如果一个 Java 类在初始化时会有外部依赖,这就给单元测试创建它的实例时造成困难。当然被测试类可以改造为依赖全部构造时注入或创建实例后延迟注入,这里不考虑这种改造。
可以参看我以前一篇类似的日志:使用 JMockit 来 mock 构造函数
来说下面的例子1public class OrderService { 2 private PriceInquiry priceInquiry = new PriceInquiry(); 3 ......... 4 5 public double totalPrice() { 6 return priceInquiry.retrieve(....); 7 } 8}
假如上面的代码是不能改动的,并且在new PriceInquiry()时依赖于网络环境,所以单机情况不能创建成功。也就使得测试时试图new OrderService();
会失败。并且试图用 Mockito 的@InjectMocks也不行 Read More
Java 8 的 Lambda 特性较之于先前的泛型加入更能鼓舞人心的,我对 Lambda 的理解是它得以让 Java 以函数式思维的方式来写代码。而写出的代码是否是函数式,并不单纯在包含了多少 Lambda 表达式,而在思维,要神似。
实际中看过一些代码,为了 Lambda 表达式而 Lambda(函数式),有一种少年不识愁滋味,为赋新词强说愁的味道。从而致使原本一个简单的方调用硬生生的要显式的用类如
apply(),accept(obj)等形式。不仅造成代码可读性差,且可测试性也变坏了。为什么说的是快乐的使用 Java 8 的 Lambda 呢?我窃以为第一个念头声明 Lambda 表达式为实例/类变量(像本文第一段代码那样),而不是方法的,一定会觉得如此使用方式很快乐的。所谓独乐乐,不如众乐乐;独乐乐,众不乐定然是更大的快乐; 更极致一些,不管什么时候必须是:我快乐,所以你也快乐。
一方面也在于 Java 还没有进化到 JavaScript 或 Scala 那样的水平,JavaScript 的函数类型变量,不一定要用
apply或call, 直接括号就能实现方法调用。Scala 的函数类型用括号调用也会自动匹配到apply或update等方法上去。 Read More
本文准确来讲是探讨如何用 Jackson 来序列化 Apache avro 对象,因为简单用 Jackson 来序列化 Apache avro 对象会报错。原因是序列化Schema getSchema()时会报错,后面会讲到,需要序列化时忽略该属性。那么能不能在getSchema()上加上@JsonIgnore来忽略该属性呢?原理上是通的。不过手工修改的 avsc 生成的 Java 文件随时会因为重新编译而还原,所以不太具有实际可操作性,当然通过定制编译 avsc 用的模板文件来加入@JsonIgnore是另一回事。
由于不能在要忽略的字段上添加JsonIgnore来控制,而如果我们明确了要忽略的字段类型的话,是能够定制 Jackson 的 ObjectMapper 来屏蔽某个特定的类型。来看下面序列化 Apache avro 对象的例子:
假设我们有一个 Apache 的 Schema 文件user.avsc, 内容如下: Read More
Java 8 引入的 Optional 类型,基本是把它当作 null 值优雅的处理方式。其实也不完全如此,Optional 在语义上更能体现有还是没有值。所以它不是设计来作为 null 的替代品,如果方法返回 null 值表达了二义性,没有结果或是执行中出现异常。
在 Oracle 做 Java 语言工作的 Brian Goetz 在 Stack Overflow 回复 Should Java 8 getters return optional type? 中讲述了引入 Optional 的主要动机。
Our intention was to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result”, and using null for such was overwhelmingly likely to cause errors.
说的是 Optional 提供了一个有限的机制让类库方法返回值清晰的表达有与没有值,避免很多时候 null 造成的错误。并非有了 Optional 就要完全杜绝 NullPointerException。
在 Java 8 之前一个实践是方法返回集合或数组时,应返回空集合或数组表示没有元素; 而对于返回对象,只能用 null 来表示不存在,现在可以用 Optional 来表示这个意义。
自 Java8 于 2014-03-18 发布后已 5 年有余,这里就列举几个我们在项目实践中使用 Optional 常见的几个用法。
Optional 类型作为字段或方法参数
这儿把 Optional 类型用为字段(类或实例变量)和方法参数放在一起来讲,是因为假如我们使用 IntelliJ IDEA 来写 Java 8 代码,IDEA 对于 Optional 作为字段和方法参数会给出同样的代码建议: Read More
最初看到 Java 9 的这个新特性没太在意,及至重新关注到 Spring 5/Springboot 2 的响应式编程的时候才真正重视起 Reactive Streams(响应式流或反应式流)。应用响应式流的编程也就叫做响应式编程(Reactive Programming),无论是翻译成反应式编程都有些令人摸不准头脑。与此对应的在 Web 设计方面有一个叫做响应式 Web 设计(Responsive web design),两个词都译作响应式,却有些差别,大概是 Reactive 被译为反应的原因之一。
通过这里对 Reactive Streams 的学习,主要目的是为了进一步掌握 Spring 5/Springboot 2 的响应式 MVC 作铺垫的,不至于猛然间见 Flux, Mono 而不知所措。
函数式响应式编程概念最早来自于九十年代末,这也激发了微软的 Erik Meijer 设计开发了 .NET 的 Rx(Reactive eXtension) 库,以及到后来 Netflix 的 RxJava 也与他有关系。Reactive Stream 更像是一种编程模式,致力于解决一个生产者产生一系列消息,一个或多个去消费它们的问题。两者的名词我们会用: producer-consumer(生产者-消费者), source/sink(水源/水槽, Akka Stream 用了这个概念), publisher-subscriber(发布者-订阅者)。
既然 Reactive Stream 和 Java 8 引入的 Stream 都叫做流,它们之间有什么关系呢?有一点关系,Java 8 的 Stream 主要关注在流的过滤,映射,合并,而 Reactive Stream 更进一层,侧重的是流的产生与消费,即流在生产与消费者之间的协调。 Read More

Java 六个月的版本迭代周期让我们突然间有些喘不过气来,又 Java 11 才会是一个长期支持版本,如果可能的话我们将会是从 Java 8 直接往 Java 11 跳去。在 Java 8 大行其道,裹足不前的当下,谈论着未来 Java 11 不确定的新特性,有一种看着别人家碗里的不过瘾,还要看着别人家锅里的感觉。
本篇原本只是为了对 Java 11 潜在的原始字符串字面量(Raw String Literals)的哨探,同时考虑到 Java 10 仅有的一个语言层面的新特性
var局部变量类型推断,所以顺带介绍一下。我这儿把它称之为 var 局部变量类型推断,说明了
var类型推断并不适用于类或实例的变量,或方法的参数。而且var也并未上升为一个 Java 的关键字,我们仍然可以用var作为变量或方法名。对局部变量用
var进行类型推断的代码示例变化如下:1List<String> list = new ArrayList<>(); //Java 10 以前 2var list = new ArrayList<String>(); //Java 10 开始 3 4int age = 100; //Java 10 以前 5var age = 100; //Java 10 开始,推断为 int 类型 6 7var stream = blocks.stream(); //都不需要引入 java.util.Stream 类var学了Scala的语法,再重复一遍,var只能用于局部变量,这有一个好处就是局部变量的跨越性较小,不至于var声明的变量阅读时只有编译器知道它的确切类型。var类型推断给代码书写上的变化就是对局部变量的任何类型声明都可以替代为var。 Read More
一年前解决了 WordPress 在 Linux 下不能发送邮件的问题,后来有段时间很正常,我的网站接收邮件的邮箱是 Gmail 的。但是近来,网站上有留言时极少收到通知邮件,怀疑是 Debian 下的exim4又不能正常工作了。但是试了如下的 PHP 脚本$ php -a
从命令行上并没有提示任何的错误,但是检查我的 Gmail 信箱,死活就是收不到邮件。即使直接用
Interactive mode enabled
php> mail('<my_gmail_account>@gmail.com', 'test subject', 'test content');
php > exitmail命令echo Hello World | mail -v -s Test <my_gmail_account>@gmail.com
也是不行的。
查看日志文件/var/log/exim4/mainlog, 发现有下面的错误信息 Read More上一篇 Linux 下配置滚动日志之 logrotate, 介绍了定时服务 logrotate 的方式对日志进行滚动,删除旧归档。logrotate 是目前流行 Linux 发行版内置的定时服务,默认每日根据配置文件来滚动日志文件。那么它可能有一个弊端就是,如果每日增长的日志超大,同时会暴盘,那么就必须调整 logrotate 这个 cron 定时服务为每小时,或自定义的 cron 表达式来控制。
而本文所介绍的 rotatelogs 工具(与 logrotate 名称太过相似) 是采用管道操作的方式来控制日志的滚动,可以基于实时监控的日志文件大小来滚动日志,也可以配置像 logrotate 来定时滚动日志。rotatelogs 是出自于 Apache HTTP Server 家族的,它被用于 Apache HTTP Server 的就错误日志,访问日志的滚动控制。
类似于 rotatelogs 的工具不有一个老旧的 cronolog,也是应用管道操作控制日志,它早已无人问津,最近更新在五年前,且功能很弱,只带滚动,不能清理旧归档,磁盘空间占用仍然是无上限。 Read More
本站已启用新域名 yanbin.blog, 博客链接已更新为 https://yanbin.blog, 完全脱离了主流域名后缀了。其实也是不得已而为之,毕竟 unmi.cc 相伴多年。在接下来的一个多月里新老域名都同时有效,已作 301 重定向,希望搜索引擎能尽快切换过来。届时 unmi.cc 将会失效,也许是一个月,也许是永远,又将为互联网创建不少死链接。
本站自 2010 年独立创建以来,一直用的就是 unmi.cc 这个域名,从 bloghost.cn 上购买的。由于后来域名都是在 GoDaddy 管理的,所以想着域名 unmi.cc 转到一块进行管理。同时也是为了防备着国内互联网公司不光在主机服务上设限制,也可能会在域名上作起文章来。
于是试图联系 bloghost.cn, 于是便是中国特色了,假若要从 bloghost.cn 买新服务,他们还算和气,但想从他们那儿转出域名,没门。看他们的网站还号称专业

别一不小心反而给他们做了个广告,其实是真不值得信赖的。他们网站上的联系方式只有 E-mail 和几个 IM 聊天号,没有电话 Read More