Hegel2011的博客

读书 - 工作 - 生活 - 笔记

DIY的好处以及雨刮和滤芯

用车两年多,有两个地方始终不太让人满意:1.雨刮器 2.空调滤芯。

个人还是比较喜欢开雨刮的,所以雨刮用的比较费,原厂的也就半年就会变花了需要更换。 之前用国产品牌carall直接替换,第一次效果还是不错的,用了4个月才花的比较厉害。 于是又去买了一对。但第二次的体验就很差,突然感觉噪音变得很大。可能小厂的品控比较差,质量高高低低的。同时,carall的价钱倒是涨的快。弄来弄去又回到了换胶条的路子上。

很早搜索论坛就得知换胶条是最经济实惠的,无奈需要diy,感觉这么个东西也没多少钱,所以最早选择 直接买了。但随着直接替换不令人满意,而且考虑到只换胶条的话,等于还能保留并继续使用原厂的雨刮臂。更重要的,本田确实是个很有意思的公司,在手册上竟然也是推荐换胶条的,并给出了怎么换的图例和说明。实际上本田的4s只卖胶条,雨刮臂很难买。于是决定自己换胶条。

自己DIY雨刮胶条之后,感觉还是很不错的。首先是成本低了很多,因为这是替换方式上形成的成本优势。只换胶条而不换雨刮臂当然比换整支雨刮臂成本低,而老化和变花的只是胶条,雨刮臂的寿命其实很长。 一对胶条的成本只在12-18元之间,一对雨刮的国产也要30-40。其次,效果方面毕竟是原厂的钢条支撑,声音就正常许多了,清晰度其实起初用用都还行。这东西关键还是在于要勤换。终于找到了一个效果、成本、难易程度都让自己满意的方案。而这一切的关键就是要DIY。

然后,最近买了几款车用空调滤芯。

  1. 韦斯特带炭
  2. 高仿本田原厂
  3. 博世不带炭
  4. 博世带炭
  5. 马勒带炭

用下来么基本还是先看滤芯结构,结构相同的情况下一分价钱一分货。 不带炭的博世是最差的,生产日期超过一年半的韦斯特也是大幅衰减的。 然而,如果给它们都盖上HEPA滤纸,可能效果就会都好很多。而这也是diy在 架构方面的胜利。

虽然购买服务是商业社会的主流选择,但DIY永远有其使用的空间。 一来社会化生产的服务归根结底也要来源于diy,二来总有社会服务提供不到位的地方也需要diy,三来补锅法锯箭法也需要diy来进行对冲。

混动雅阁

混动雅阁千呼万唤历经两年时间终于摆在了中国消费者的面前。而其定价也可谓 相当合理:

  • 酷版: 23.98万元
  • 领版: 25.98万元
  • 尊版: 27.98万元

价格基本和2.4版本的衔接,并且顶配也没超过原来3.0的次顶配。 因此,这个价钱是定的相当有诚意。

本田在日系里还是有点运动基因,所以那种混动也走向sporty的道路, 发挥了电机启动快扭矩大的优势。电池给了10年保也算负责了。

但是,仔细看看混雅的配置,尤其是丐版的,还是过于寒酸了。

  1. 2款低配没有后雷达,而顶配有前后雷达
  2. 最低配没有驾驶座电动调节
  3. 最低配没有车载蓝牙

以上3者都是我认为不可缺少的现代汽车的配置。那么就只能上27.98万元这个版本, 而这个价位下,A4 三系在品牌上的优势就大了。所以混雅的前途大概只是投石问路。 希望这套系统早日用在CRV上。

装机i5-6500

许久没有装机了,入了如下的配置:

  • intel i5-6500 1150元,
  • 散热器采融B48 99元,
  • 技嘉 B150M-D3H 599元,
  • 芝奇 DDR4 2400 395元,
    合计2243元

1.货物来源

某宝买散片和散热器,某东买入主板和内存。原因在于散片确实比盒装的便宜很多,差价在300的样子,而京东等电商基本不做散片的生意。主板的价格相对统一的多,内存差价也不大,所以就还是京东买了。

2.cpu插座保护盖及安装注意事项

自己diy还是有一定的风险。而且自己装cpu还是第一次,一开始搞主板的cpu保护插座还费了点事情。好在有惊无险。这个保护盖一定不要先揭走,而是要等到安装完cpu后自己会弹出来。主要是保护插座上的针脚。iU现在本身只有垫片了,针脚全在主板上,所以主板容易弄坏。

3.散热器的安装,包括硅胶涂在cpu上

cpu安装好,压好架子后就可以涂硅胶装散热器了。硅胶可以用九点法后直接压上去,也可以涂在中间,然后用散热器磨开来。我用的是后面这个法子。一般都应该行得通,反正只是为了保证散热器和cpu的接触面积。 分散和散热器采融48采用的是搭扣,其实就是靠线扣的弹力自己箍上去的。

4.UEFI与GPT和win10

技嘉这个新板子默认就是UEFI的界面,比bios启动快一些吧。win10装好,10秒内可以启动成功。2年前买的ssd终于找到了相得益彰的平台。

5.网卡驱动,win10默认也没有

即使装了win10,网卡驱动也要另外装的,默认并不提供。

6.vpn拨号

如果拨号成功还不行,可以尝试一下禁用IPv6.

附最近12年的配过的自己的机器,应该还漏了一台

2004年4月买的,花了38xx

AMD barton 2500+
KST 512M ddr400
日立硬盘 7k250 120g/2m
华硕 a7v600-x 主板
迪兰横进 9600pro 显卡

2011年买入,花了2615元

AMD Athlon II X4 640 699元,
4GB KST DDR1333,300元
技嘉 MA770T-UD3P 主板,
华硕EAH5750显卡,
安钛克BP430plus电源 300元,
机箱,
无硬盘

老婆的:

2010年11月购入,合计花了4249.00元

Intel 英特尔 奔腾双核 E6500 (2.93GHz/LGA775/2M/1066MHz/45纳米)盒装 519元,
威刚 DDR3 1333 2G 内存 178元,
华硕 P5P54TD主板 569元,
华硕 ENGT40/512M 显卡 539元,
希捷 1TB硬盘 408元,
酷冷至尊 破坏者塔式机箱 229元,
ACBEL 康舒 IP-430台式机电源(额定功率380w/ATX2.3版) 电源 229元,
Samsung 三星 2494LW 23.6英寸宽屏液晶显示器 1285元,
微软多媒体键盘 79元

Spring Boot in Action

  • Auto-Config
  • 用starter处理依赖
  • CLI 命令行处理启动等
  • Actuator 监控组件 , 通过web或者shell
1
2
3
spring version 
spring --version
spring shell # windows下打开可以自动补全的功能

工程初始化

1
2
spring init -dweb,jpa,security --build gradle -p jar -x //-x表示生成到当前目录
spring init -dweb,jpa,security --build gradle -p war myapp //表示生成工程到myapp目录
1
2
3
4
5
6
7
@SpringBootApplication
public class DemoddfApplication {

public static void main(String[] args) {
SpringApplication.run(DemoddfApplication.class, args);
}
}

@SpringBootApplication 起到了过去3个标注的作用,打开了自动配置和自动扫描。如果有新的配置要求,@Configuration用在其他配置类中进行配置的扩充。而主class可以不必修改

用starter定义可实现更高度的抽象,也不必给出每个组件的版本号。通过mvn dependency:tree可查看实际的包依赖关系. starter就是普通的maven或gradle依赖,所以可以exclude也可以指定更直接的版本。

自动配置定制化的举例

安全是最好的需要自己自行设置的例子,not one–size-fits-all。 这是yml方式

1
2
3
4
5
6
server:
port: 8443
ssl:
key-store: file:///path/to/mykeys.jks
key-store-password: letmein
key-password: letmein

配置数据源

1
2
3
4
5
6
spring:
datasource:
url: jdbc:mysql://localhost/readinglist
username: dbuser
password: dbpass
driver-class-name: com.mysql.jdbc.Driver

属性信息的几种来源

  1. Command-line arguments
  2. JNDI attributes from java:comp/env
  3. JVM system properties
  4. Operating system environment variables
  5. Randomly generated values for properties prefixed with random.* (referenced when setting other properties, such as `${random.long})
  6. An application.properties or application.yml file outside of the application
  7. An application.properties or application.yml file packaged inside of the application
  8. Property sources specified by @PropertySource
  9. Default properties

在application.properties中指定spring.profiles.active的值后,boot就会读取application-{active}.properties的值

自动化测试

@WebIntegrationTest Test class有这个标注就会让spring启动一个测试的tomcat或jetty进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(
classes=ReadingListApplication.class)
@WebIntegrationTest

public class SimpleWebTest {
@Test(expected=HttpClientErrorException.class)
public void pageNotFound() {
try {
RestTemplate rest = new RestTemplate();
rest.getForObject(
"http://localhost:8080/bogusPage", String.class);
fail("Should result in HTTP 404");
} catch (HttpClientErrorException e) {
assertEquals(HttpStatus.NOT_FOUND, e.getStatusCode());
throw e;
}
}
}

代入参数 @WebIntegrationTest(value={"server.port=0"})@WebIntegrationTest("server.port=0")

selenium的用ie模拟访问自己的服务很有意思,值得制作一个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
            FirefoxDriver browser = new FirefoxDriver();
browser.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
String baseUrl = "http://www.baidu.com/";
browser.get(baseUrl);
String currentUrl = browser.getCurrentUrl();
assertEquals(baseUrl +"/readingList", currentUrl);

assertEquals("You have no books in your book list",
             browser.findElementByTagName("div").getText());

browser.findElementByName("title").sendKeys("BOOK TITLE");
browser.findElementByName("author").sendKeys("BOOK AUTHOR");
browser.findElementByName("isbn").sendKeys("1234567890");
browser.findElementByName("description").sendKeys("DESCRIPTION");
browser.findElementByTagName("form").submit();

WebElement dl =
    browser.findElementByCssSelector("dt.bookHeadline");
assertEquals("BOOK TITLE by BOOK AUTHOR (ISBN: 1234567890)",
             dl.getText());
WebElement dt =
    browser.findElementByCssSelector("dd.bookDescription");
assertEquals("DESCRIPTION", dt.getText());

《Selenium WebDriver in Practice》但还没完成,可能要到2016年10月份才能出版

/beans 列出创建的全部bean
/autoconfig 列出自动配置生效和未生效的内容
/env 列出设置的环境
/configprops 列出所有的参数
/metrics 列出访问的指标
/trace 给出近100个http请求的处理信息
/dump 给出所有线程的情况
/health 表明是否UP
/info 列出属性文件中info.开头的信息,但似乎有乱码

actuator的remote shell 默认启动一个端口在2000,每次启动时会生成一个密码,可以用ssh访问

1
2
3
ssh user@localhost -p 2000
Password authentication
Password:

自己定义metrics:

actuator有CounterService服务,可以用于增加值。

1
2
3
4
5
public interface CounterService {
void increment(String metricName);
void decrement(String metricName);
void reset(String metricName);
}

GaugeService是记录值

1
2
3
public interface GaugeService {
void submit(String metricName, double value);
}

自定义Health

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component
public class AmazonHealth implements HealthIndicator {
@Override
public Health health() {
try {
RestTemplate rest = new RestTemplate();
rest.getForObject("http://www.amazon.com", String.class);
return Health.up().build();
} catch (Exception e) {
return Health.down().build();
}
}
}

//还可以加入更多的细节内容,使用withDetail

return Health.down().withDetail("reason", e.getMessage()).build();

上述endPoint的保护需采用所有spring暴露的链接一致的方式

management.context-path=/mgmt,其中的management.context-path可以给spring actuator定义全部的前缀

这样可便于统一控制 .antMatchers("/mgmt/**").access("hasRole('ADMIN')")

部署时调整production环境变量

@Profile("production")

export SPRING_PROFILES_ACTIVE=production

最简单的是export active的环境变量为production

spring的db migrate,不算很实用吧

Spring Boot includes auto-configuration support for two popular database migration libraries:
■ Flyway (http://flywaydb.org) — 直接采用SQL编写ddl
■ Liquibase (www.liquibase.org) — 使用yaml json等

附录

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>

开发工具具备自动重启的功能,但下面这些静态资源默认是exclude的: /META-INF/resources, /resources, /static, / public, /templates.

关于冠道

本田的冠道近日宣传的比较多,虽然价格还没最后公布,但车还是造成了足够的话题。 因为这车既是本田目前的旗舰suv,也是首次使用了2.0T发动机的中国产本田车型。

其实这个车挺像昂科威的,只是更高级也更大些。CRV相对这类车,最大的优势还是在于尺寸、操控,尤其是尺寸相对冠道的优势更大。毕竟CRV这种4米6以下的长度,1米8左右的宽度,在城市开还是挺舒服的,再搭配一个装载能力很大的尾箱,是各方面都很均衡的车型。 而冠道,对拥挤的中国城市来讲,它的尺寸还是大了些。而尺寸大的车,操控必然是要打折扣的。 而从空间看,尾箱部分因为溜背造型,并不如crv的尾箱实惠。 油耗、可靠性方面可能也是crv更有优势些。 当然,同昂科威一样,冠道内饰的高级感、拥有税金更省的涡轮、拥有at变速箱、静音等方面都是对crv碾压了。

不过问我会不会买冠道?只要这个车不是比crv便宜,那肯定还是crv,毕竟crv开着更舒服。

Nginx 通过Lua输出response Body

Nginx默认是不只支持$request_body 而不支持response的body输出的。这个设定是合理的,因为大量的html响应或者静态文件的内容输出将使得整个日志毫无意义。 然而,response body输出对api的请求来讲,则很多时候、尤其是在调试的时候是很有必要的。取代了抓包的作用,且简单直观许多。 搜寻之下,发现使用lua的话,可以达到此目的。

  1. 下载并安装lua语言的安装包
1
2
3
4
 wget http://luajit.org/download/LuaJIT-2.0.3.tar.gz
tar -zxvf LuaJIT-2.0.3.tar.gz
cd LuaJIT-2.0.3.tar.gz
make && make install

注意,可能你的服务器的wget会实际下载一个html到本地导致tar解压失败,此时可以用浏览器下载完毕后再次上传到服务器上。

  1. 下载并解压ngx_devel_kit套件
1
2
wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.19.tar.gz
tar v0.2.19
  1. 下载并解压lua-nginx-module模块
1
2
wget https://github.com/chaoslawful/lua-nginx-module/archive/v0.9.6.tar.gz
tar v0.9.6
  1. 下载并解压nginx后,使用下面的命令重新编译nginx
1
2
3
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_flv_module --with-http_gzip_static_module --with-pcre --sbin-path=/usr/sbin/nginx --add-module=/root/lua-nginx-module-0.9.6 --add-module=/root/ngx_devel_kit-0.2.19 
make && make install
cp /usr/sbin/nginx /usr/local/nginx/sbin/

最后,在nginx的conf文件中的server{}上下文里加入下面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
log_format  main_with_response  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"'
                      'request: "$request_body"' 'response: $resp_body';

server {

...
   lua_need_request_body on;
    set $resp_body "";
    body_filter_by_lua '
        local resp_body = string.sub(ngx.arg[1], 1, 1000)
        ngx.ctx.buffered = (ngx.ctx.buffered or "") .. resp_body
        if ngx.arg[2] then
             ngx.var.resp_body = ngx.ctx.buffered
        end
    ';

       location /xxxx {
            root   html;
            access_log  logs/access.log  main_with_response;
            proxy_pass http://192.168.203.198:8080;
        }

}

为避免response溢出整个日志,可选择在特定的location中使用输出response body。

车险

时间很快,CRV买了快要一年了,又到了车险续保的日子。过去的11个月还算基本顺利,车子没遇到大的损害, 只有一些小的刮蹭。本来想用划痕险统一处理一下,但又担心来年保费政策大变化,所以还是没用。

因为没有出险,所以商业险给打了七折,下面是对比

  • 车损:现2109.58,原3514.15
  • 三责:现1176, 原1689.48
  • 盗抢:现取消, 原977.02
  • 划痕:现339.5, 原486.35
  • 各项不计免赔:现543.77,原1049.04

总体折扣尤其是车损的折扣比7折还是要低不少的。那么问题来了,明明是7折,怎么反而会更低呢?难道政府控制的 保险公司是活雷锋?

非也。差的多的主要是车损,而对比两份保单,可以发现原先的保额是249441元,然而新的是224475元,这就 差了近10%。经过一番搜索,发现其实保额的计算是这么来的:车厂的出厂原价+10%的购置税。所以从天籁到crv, 甚至是跑在中国马路上的其他私家车,金额都会稍大。CRV今年比去年车损保额降了10%,应该是总理新政的功劳。

与去年不同,盗抢险这次取消掉了,毕竟生活在上海,发生车辆被盗又不被找回的概率是很低很低的,还是不买了吧。

StringHttpMessageConverter的头属性

使用Spring MVC中的@ResponseBody或者@RestController产生的json消息格式会产生一个很大的响应头。 其主要内容就是Accept-Charset会罗列几乎所有的charset变量,从utf到gbk再到iso等等。而这很大程度上是无谓的开销。

要解决可以在xml的配置中设置

1
2
3
4
5
6
7
8
9
  <mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
      <!-- 将StringHttpMessageConverter的默认编码设为UTF-8 -->
      <bean class="org.springframework.http.converter.StringHttpMessageConverter">
        <constructor-arg value="UTF-8" />
        <property name="writeAcceptCharset" value="false" />
      </bean>
    </mvc:message-converters>
  </mvc:annotation-driven>

注意给StringHttpMessageConverter的属性writeAcceptCharset设置成false

—- update on 2016.10.17

RestTemplate作为客户端发送请求时也有类似的问题,会带出一串过长的Charset。解决办法如下:

1
2
3
4
5
6
7
8
9
static RestTemplate restTemplate = new RestTemplate();
  static {
    List<HttpMessageConverter<?>> converts = restTemplate.getMessageConverters();
    for (HttpMessageConverter<?> convert : converts) {
      if (convert.getClass() == StringHttpMessageConverter.class) {
        ((StringHttpMessageConverter) convert).setWriteAcceptCharset(false);
      }
    }
  }

获得converts,然后对String的Convert进行设置

Included file 'twitter_sharing.html' not found in _includes directory