2016年7月4日星期一

docker,boot2docker,dns,network

VirtualBox里的那个docker,外面网络切换时,VirtualBox里的boot2docker加上更里面的容器就都网络不通了。一开始还以为是自己的网络问题,几次之后发现这似乎是boot2docker的bug,不是网络不通,而是DNS server没有自动随机而变,还在用一开始主机网络时的那个,自然不通了。

解决方法有几种,我一开始是傻傻的重启动boot2docker的。
  • 启动docker容器时指定--dns 8.8.8.8
    docker run -it --dns 8.8.8.8 ubuntu bash
    
  • 修改一下boot2docker的 /etc/resolv.conf
    nameserver 8.8.8.8
    
  • 重启动boot2docker(也就是docker-machine)
    docker-machine restart default

Created an non-root docker image for .NET Core 1.0 so you no worry about yemon or npm's anti-root problem

When use the docker image of .NET Core 1.0 from microsoft/dotnet, have you ever encountered `permission denied '/root/.config/configstore/.....` or `No native-sleep available` or `NuGet Cache` error or some weird problem concerned with file permission about /usr/local?
That's why i build a docker image.

Dockerfile is here. I have pushed to docker hub as osexp2000/dnetcore_docker_image.

dnetcore_docker_image

An non-root docker image for .NET Core development( having created normal user id with sudoable, installed nodejs, yeoman, aspnet generator...), you won't worry about yeomen's anti-root problem and some other permission problem about /usr/local.
Usage:
To just use the docker image:
docker run -it osexp2000/dnetcore_docker_image
You will get a bash running with normal user id named dev_user which can sudo without password.
Then you can run aspnet generator:
yo aspnet
And also installed some other utilities vim,lsofnetstat.
A screenshot:
$ docker run -it osexp2000/dnetcore_docker_image
dev_user@640be8c28a81:~$ id
uid=1000(dev_user) gid=1000(dev_user) groups=1000(dev_user),27(sudo)
dev_user@640be8c28a81:~$ yo aspnet
? ==========================================================================
We're constantly looking for ways to make yo better!
May we anonymously report usage statistics to improve the tool over time?
More info: https://github.com/yeoman/insight & http://yeoman.io
========================================================================== Yes

     _-----_     ╭──────────────────────────╮
    |       |    │      Welcome to the      │
    |--(o)--|    │  marvellous ASP.NET Core │
   `---------´   │        generator!        │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? What type of application do you want to create? (Use arrow keys)
❯ Empty Web Application
  Console Application
  Web Application
  Web Application Basic [without Membership and Authorization]
  Web API Application
  Class Library
  Unit test project (xUnit.net)

To build it yourself:
docker build -t IMAGE_NAME_HERE --rm https://raw.githubusercontent.com/sjitech/dnetcore_docker_image/master/Dockerfile
or download the Dockerfile then run:
docker build -t IMAGE_NAME_HERE --rm - < Dockerfile

.NET Core 1.0学习(3)-做了个靠谱点的docker image)

本来想进一步做aspnet的练习,结果在docker里练到"Building Projects with Yeoman"的地方就碰到了yeomon那些鸟人故意搞的"去root化"问题,用root执行它就唧唧歪歪爆无聊的错,一个个硬chmod是可以,但是不爽,干脆就自己做个Dockerfile生成一个能够在里面开发的docker image吧,全当练习Docker Image制作了。

碰到的错误就是那permission denied '/root/.config/configstore/insight-yo.yml'呀,Attempt To Unlock * Which Hasn't Been LockedNuGet cache之类的错误。前者是yemon的,后者是nodejs安装的不够新(apt-get install nodejs的是0.10级别的版本,谁想的到啊)
做好的docker image叫osexp2000/dnetcore_docker_image (或者osexp2000/dnetcore,更新快些)。
docker run -it osexp2000/dnetcore_docker_image
进去之后就是bash,以dev_user用户运行在/home/dev_user,这个用户能够sudo(无需密码)。
进去就可以顺利的运行aspnet模版生成工具yeomen了。
yo aspnet
里面什么npm和yeomen之类的东西都准备好了,甚至基本的vim,lsofnetstat之类的都准备好了,不然真不方便查看环境。
运行的样子是这样的:
$ docker run -it osexp2000/dnetcore_docker_image
dev_user@640be8c28a81:~$ id
uid=1000(dev_user) gid=1000(dev_user) groups=1000(dev_user),27(sudo)
dev_user@640be8c28a81:~$ yo aspnet
? ==========================================================================
We're constantly looking for ways to make yo better! 
May we anonymously report usage statistics to improve the tool over time? 
More info: https://github.com/yeoman/insight & http://yeoman.io
========================================================================== Yes

     _-----_     ╭──────────────────────────╮
    |       |    │      Welcome to the      │
    |--(o)--|    │  marvellous ASP.NET Core │
   `---------´   │        generator!        │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

? What type of application do you want to create? (Use arrow keys)
❯ Empty Web Application 
  Console Application 
  Web Application 
  Web Application Basic [without Membership and Authorization] 
  Web API Application 
  Class Library 
  Unit test project (xUnit.net)

Dockerfile放在这儿了。很少,干脆贴下来。
FROM microsoft/dotnet

RUN apt-get update

#install nodejs 6.x
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get install -y nodejs


#install aspnet generator
RUN npm install -g yo bower grunt-cli gulp
RUN npm install -g generator-aspnet




#this must be installed
RUN apt-get install -y sudo


#these are optional utilities
RUN apt-get install -y vim
RUN apt-get install -y bash-completion
RUN apt-get install -y lsof
RUN apt-get install -y net-tools
RUN apt-get install -y man
RUN apt-get install -y less
RUN apt-get install -y netcat



#add developer user
RUN adduser --disabled-password --gecos "Developer" dev_user
RUN adduser dev_user sudo
RUN echo "dev_user ALL=(ALL:ALL) NOPASSWD: ALL" | (EDITOR="tee -a" visudo)


#optional aliases
RUN echo 'alias ll="ls -lFa"' >> ~/.bashrc
RUN echo 'alias ll="ls -lFa"' >> /home/dev_user/.bashrc

#this is also important so yomen will not complains
RUN chown -R root:sudo /usr/local

RUN rm -f /core
RUN rm -fr /tmp/NuGetScratch

USER dev_user
WORKDIR /home/dev_user
可以自己存起来build成docker image
docker build -t IMAGE_NAME_HERE --rm - < Dockerfile

下次再沿着Your First ASP.NET Core Application on a Mac Using Visual Studio Code — ASP.NET documentation继续学。不过我想看看如何通过Mac OS X里的Visual Studio Code来直接把代码发布到docker里。

.NET Core 1.0学习(2)

做了个简单的aspnet练习,再总结一下上次的经验

随便照着[Getting Started — ASP.NET documentation做了一下练习,实在无趣。就是改个project.json再写个hello world。
什么Code Behind(aspx, aspx.cs),事件代码的, 都没看到。(就看Visual Studio Code的本事了,不然就没有微软特色了)
贴个代码结束 (用的不是和IIS或者IIS Express配套的那个ASP.NET,想用也没有。而是Kestrel,名字是一种鸟,鸟Server?)。
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;

namespace aspnetcoreapp
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            app.Run(context =>
            {
                return context.Response.WriteAsync("Hello from ASP.NET Core!");
            });
        }
    }
}
再回想起上次练习.NET Core 1.0学习(1),发现了几点不同寻常的地方:
  1. .NET Core的东西好精简。加起来才180个文件左右,109M左右。都放在/usr/share/dotnet下。 (毋庸置疑,里面也包含了ASP.NET Core的东西,我做了简单的aspnet试了OK。$HOME/.nuget下的东西和dotnet下的东西雷同很多。)
    反正比起Windows上那一坨坨的实在清爽太多。
    可是为啥能够少这么多呢? (1)大量的Windows GUI相关的东西去掉了,我没有看到任何和form相关的东西。更不要提那劳什子WPF,Silverlight了。 (2)一个是Windows上的GAC去掉了,估计连功能都没做。 (3)ASP.NET的东西似乎极少,都没看到以前的System.Web.Dll。
  2. IIS不见踪影 也没看见什么Express的字样。 做最初的aspnet的例子时发现是用Microsoft.AspNetCore.Server.Kestrel来做Server的,靠谱吗?不知道,看了github里的介绍aspnet/KestrelHttpServer,不冷不热吧,都没怎么看见宣传,说好的IIS Express呢?
  3. 看见了libuv的身影。 这东西才是NodeJS的半壁江山,异步事件驱动高效而且跨平台的lib。上面提到的KestrelHttpServer就是用它做的,难怪这么小。
    突然想起来,以前IIS特意把HTTP的一些处理放倒内河层做(http.sys)以便快速的处理request/response, IIS的速度也的确挺强悍,可是现在不用这个体制会怎么样?如果能够很好,那么为什么还要做的那么啰嗦。看来微软也被libuv征服了,这是应该的。
  4. 看见了VB的身影 /root/.nuget/packages/Microsoft.VisualBasic/10.0.1/ref/netcore50/Microsoft.VisualBasic.dll看来也许会支持,其实也不是什么大事儿,因为画面是甭指望的了,有没有他谁还在乎。

微软扔掉了UI,赤膊到Linux上拼搏,优势大减啊。.NET Runtime本身的速度和Java VM的相比自然不能快到哪里去,否则JVM必然会超过。 这个.NET Core搞好了,大家当然都愉快,就看微软给不给力了,可别来个太粗暴的一刀切什么的。

2016年7月3日星期日

.NET Core 1.0学习(1)-看看环境

不够成熟是肯定的,就想看看Linux上的.NET Core到了那步了。

好奇环境是怎样的,先不看任何东西,自己翻翻看。
  • 不想折腾环境,运行一个docker容器就一把搞定了。
    docker run -it microsoft/dotnet:latest
    
  • 新建一个工程,流行的风格,嗯,挺上路的吗。
    mkdir hwapp
    cd hwapp
    dotnet new
    
    看看目录结构
    -rwxr--r-- 1 root root    202 Jun 22 03:31 Program.cs*
    -rwxr--r-- 1 root root    348 Jun 22 03:31 project.json*
    
    挑个小刺:每个文件居然全设定成了可执行属性,看着就怪啊。 Program.cs就一个Hellow World没啥看头。 project.json:
    {
    "version": "1.0.0-*",
    "buildOptions": {
      "debugType": "portable",
      "emitEntryPoint": true
    },
    "dependencies": {},
    "frameworks": {
      "netcoreapp1.0": {
        "dependencies": {
          "Microsoft.NETCore.App": {
            "type": "platform",
            "version": "1.0.0"
          }
        },
        "imports": "dnxcore50"
      }
    }
    }
    
    也还好。 dnxcore50的名称以后可能会换掉。哎,.NET本身的名称都不好,上梁不正下梁歪。
    小刺:最好直接换成yaml,都有点烦了JSON了,那双引号,什么破设计,另外也不能写注释。所以人家SpringBoot默认都换成yaml了。
  • 开始安装依存lib然后执行了
    dotnet restore     #####这个命令吓人,求你改掉吧。实际是相当于npm install的意思,安装依赖lib#####
    dotnet run
    
    自然是得到了Hello World。
    编译生成的目录和Windows下的习惯一样,bin/Debug,和obj
    bin/Debug/netcoreapp1.0/hwapp.dll
    bin/Debug/netcoreapp1.0/hwapp.deps.json
    bin/Debug/netcoreapp1.0/hwapp.pdb
    bin/Debug/netcoreapp1.0/hwapp.runtimeconfig.dev.json
    bin/Debug/netcoreapp1.0/hwapp.runtimeconfig.json
    
  • 看看这个dotnet是何方神圣
    root@88dab4dc4160:/hwapp# ls -lF `which dotnet`
    lrwxrwxrwx 1 root root 24 Jun 30 21:00 /usr/bin/dotnet -> /usr/share/dotnet/dotnet*
    
    干脆把/usr/share/dotnet/下的东西都翻出来看看
    ./dotnet
    ./host/fxr/1.0.1/libhostfxr.so
    ./sdk/1.0.0-preview2-003121/corehost  #这个显然是主角luancher了
    ./sdk/1.0.0-preview2-003121/libhostfxr.so
    ./sdk/1.0.0-preview2-003121/libhostpolicy.so
    ./shared/Microsoft.NETCore.App/1.0.0/corehost
    ./shared/Microsoft.NETCore.App/1.0.0/dotnet
    ./shared/Microsoft.NETCore.App/1.0.0/libclrjit.so      #JIT Compiler
    ./shared/Microsoft.NETCore.App/1.0.0/libcoreclr.so     #CLR运行时
    ./shared/Microsoft.NETCore.App/1.0.0/libcoreclrtraceptprovider.so
    ./shared/Microsoft.NETCore.App/1.0.0/libdbgshim.so 
    ./shared/Microsoft.NETCore.App/1.0.0/libhostfxr.so
    ./shared/Microsoft.NETCore.App/1.0.0/libhostpolicy.so
    ./shared/Microsoft.NETCore.App/1.0.0/libmscordaccore.so
    ./shared/Microsoft.NETCore.App/1.0.0/libmscordbi.so
    ./shared/Microsoft.NETCore.App/1.0.0/libsos.so
    ./shared/Microsoft.NETCore.App/1.0.0/libsosplugin.so
    ./shared/Microsoft.NETCore.App/1.0.0/libuv.so    ##居然你也在。异步编程用的。Node.JS里用它做event loop的。
    ./shared/Microsoft.NETCore.App/1.0.0/System.Globalization.Native.so
    ./shared/Microsoft.NETCore.App/1.0.0/System.IO.Compression.Native.so
    ./shared/Microsoft.NETCore.App/1.0.0/System.Native.so
    ./shared/Microsoft.NETCore.App/1.0.0/System.Net.Http.Native.so
    ./shared/Microsoft.NETCore.App/1.0.0/System.Net.Security.Native.so
    ./shared/Microsoft.NETCore.App/1.0.0/System.Security.Cryptography.Native.so
    
    这应该就是最核心的干货了。
    还有其他好多dll的,和xarmarine里的那一套比较像
    ./sdk/1.0.0-preview2-003121/.version
    ./sdk/1.0.0-preview2-003121/csc.deps.json
    ./sdk/1.0.0-preview2-003121/csc.dll
    ./sdk/1.0.0-preview2-003121/csc.runtimeconfig.json
    ./sdk/1.0.0-preview2-003121/dotnet.deps.json
    ./sdk/1.0.0-preview2-003121/dotnet.dll
    ./sdk/1.0.0-preview2-003121/dotnet.runtimeconfig.json
    ./sdk/1.0.0-preview2-003121/Microsoft.ApplicationInsights.dll
    ./sdk/1.0.0-preview2-003121/Microsoft.DiaSymReader.dll
    ./sdk/1.0.0-preview2-003121/Microsoft.DotNet.Archive.dll
    ...
    ./sdk/1.0.0-preview2-003121/Microsoft.DotNet.Configurer.dll
    ...
    ./sdk/1.0.0-preview2-003121/Microsoft.Extensions.Testing.Abstractions.dll
    ./sdk/1.0.0-preview2-003121/Newtonsoft.Json.dll
    ./sdk/1.0.0-preview2-003121/NuGet.Client.dll
    ./sdk/1.0.0-preview2-003121/NuGet.CommandLine.XPlat.dll
    ...
    ./sdk/1.0.0-preview2-003121/NuGet.RuntimeModel.dll
    ./sdk/1.0.0-preview2-003121/NuGet.Versioning.dll
    ./sdk/1.0.0-preview2-003121/nuGetPackagesArchive.lzma
    ./sdk/1.0.0-preview2-003121/runtimes/unix/lib/netstandard1.3/System.Diagnostics.TraceSource.dll
    ./sdk/1.0.0-preview2-003121/runtimes/win-x64/native/Microsoft.DiaSymReader.Native.amd64.dll
    ...
    ./sdk/1.0.0-preview2-003121/runtimes/win8-arm/native/Microsoft.DiaSymReader.Native.arm.dll
    ./sdk/1.0.0-preview2-003121/System.Diagnostics.TextWriterTraceListener.dll
    ...
    ./sdk/1.0.0-preview2-003121/System.Xml.XmlSerializer.dll
    ./shared/Microsoft.NETCore.App/1.0.0/Microsoft.CodeAnalysis.CSharp.dll
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/Microsoft.VisualBasic.dll  #VB.NET难道也要支持,扔了算了。
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/Microsoft.Win32.Registry.dll  #Registry??
    ./shared/Microsoft.NETCore.App/1.0.0/mscorlib.dll
    ./shared/Microsoft.NETCore.App/1.0.0/mscorlib.ni.dll
    ./shared/Microsoft.NETCore.App/1.0.0/sosdocsunix.txt
    ./shared/Microsoft.NETCore.App/1.0.0/System.AppContext.dll
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/System.IO.dll  #亲切
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/System.Native.a  #这是给谁用啊
    ./shared/Microsoft.NETCore.App/1.0.0/System.Net.Http.dll
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/System.Reflection.dll
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/System.Runtime.dll
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/System.Runtime.InteropServices.dll  #这是什么节奏, Native调用吗?
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/System.Runtime.Loader.dll
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/System.Security.Cryptography.Csp.dll
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/System.Security.Cryptography.OpenSsl.dll
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/System.Text.RegularExpressions.dll
    ...
    ./shared/Microsoft.NETCore.App/1.0.0/System.Xml.ReaderWriter.dll
    ./shared/Microsoft.NETCore.App/1.0.0/System.Xml.XDocument.dll
    ...
    
    另外,机器里面还有一些.nuget管理包用的目录, 整体很干净。
    继续吐槽,NuGet这样的名称还不趁机改掉啊,难受死了。
    回头再接着分析。
  • 看看corehost,和如何debug。 看了corehost的命令行,回到hwap目录下试着用一下
    root@88dab4dc4160:/hwapp# /usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0/corehost ./bin/Debug/netcoreapp1.0/hwapp.dll
    Hello World!
    
    看来就是他了,好了,入口找到了。
    再看看详细信息,下次再分析一下。
    root@88dab4dc4160:/hwapp# COREHOST_TRACE=1 /usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0/corehost ./bin/Debug/netcoreapp1.0/hwapp.dll 2>&1 |less
    一堆结果爆屏,不贴了,能够看到用到什么文件。
    ...
    
    dotnet和corehost的命令行帮助太少,看不出如何debug,但肯定能够调试,只是这些细节看来还没做完备啊。
    下次在看看如何debug。然后在学学ASP.NET Core。

2016年7月1日星期五

.NET Core 1.0会不会成为Vista?真为他捏一把汗

从此以后没有后续的ASP.NET了,愿意不愿意都只能用跨平台的.NET Core里了,除非用老的ASP.NET。

微软勇气非凡,终于把.NET Runtime, IIS集成进去了, 但是什么程度就不清楚了,我得赶紧来找个能动的docker image体验一下.net core。
可以想象这个一旦用起来,影响巨大,微软会不会忙死,还是按照开源那一套路走,让开发者自己改?
这次改动太大了,真的有点Vista的风格,居然把ASP.NET给停了,这又是哪个领导拍脑子决定的。
想想看,微软的“隔代旺”: Me失败 -> XP成功 -> Vista失败 -> Win7成功 -> 8失败 -> 10成功。
据说他还要收购Docker,连起来就知道微软意图重新争霸。

Java什么时候提高境界支持async/await写法啊?

异步编程的写法,没有比.Net/JavaScript里的async/await更“优雅并且好懂”的了(.NET的2012年就出来了),可到现在,Java都没有,还没听到定论说Java9要支持。难道是微软掐住了专利,导致别的语言无法普及吗。Java你得有紧迫感啊,虽然你现在是老大,但不上进的话也会被人赶上哦。

异步编程的最高境界,就是根本不用关心它是不是异步
.NET的async/await方式最先达到了这个境界。
和async/await写法相比,Java的什么ExecutorService以及回调之类设计都是惭愧无比的。当然,习惯了也没啥,反正那Java的lamda表达式用着也可以接受。
人不知道更好的东西的时候其实也就无所谓难受,更何况现在Java强势,.NET就算有好东西也发不出太大的影响...
不过可以想象,如果Java9支持了这个写法,那么那些RxJava什么的和回调有关系的各种lib都会成为二等公民(对于某数据流式处理还是需要的)。
其实那么多牛人,怎么会想不到这点呢,为啥还不改呢?也许是不想承受抄袭的骂名,而是想改得直接超越.NET的,也许是专利限制,谁知道呢。
想来又不是要改JVM,只是改点编译器罢,支持把await的后的代码自动编程回调函数,再把系统的一些费时间的method给多封装一个返回AsyncResult<SomeReturnType>之类的method,多大的事儿啊,改了吧。
那些getter/setter不支持的事儿就不和你计较了,反正还有个Lombk预编译加上@Gettr/@Setter之类的就可以了。可这个async/await不然,就不容易由第三方用类似的方法实现了。

顺便普及一下async+await是如何优雅的,最自然的语法,天才的想法。思路大致是这样:
  1. 假设先做个很重的API,为了异步,那就立刻返回一个AsyncResult<真实返回类型>,就是不是立刻得到结果的那种,同时在单独的线程池里执行本来的动作。 一般的编程模式是,让用户通过回调来处理结果:
    string someFunction() {
     AsyncResult<真实返回值类型> asyncResult = someApi(...);
     asyncResult.onComplete( 真实结果 -> {
         ...对结果的处理...
     } );
     return something;
    }
    
  2. 就在这时,有哪位聪明人,觉得可以让编译器作者事儿,只要代码里加个标记就行了,这就是await的登场了
    string someFunction() {
     真实返回值类型> result = await someApi(...);
     ...对结果的处理...
     return something;
    }
    
    相当于编译器自动把await语句后面的知道函数末尾的所有语句都编译成了一个临时的Lamda表达式了。
  3. 但是这样一来,异步的特性会逐层传染,当前所在的函数someFunction也就立刻返回了,那到底返回成什么好呢,这就是async的登场了。
    async string someFunction() {
     真实返回值类型> result = await someApi(...);
     ...对结果的处理...
     return something;
    }
    
    这就是告诉编译器,谁要是调用someFunction,他也必须用await罩一下。
    string x = await someFunction()
    ...
    
    就这么想着想着改巴改巴就成了。
    更具体的,就随手转帖一个有关.NET async/await的实现背后 « 司维的思维

async/await多美啊,实在符合自然思维,看到await,就明白后面的代码会等会儿再执行,暂时可以回家吃饭去了。
但是,也有缺点,await只能取得一个结果,然后就不搞了。 这对于陆陆续续出若干个结果的API,就没什么作用,难道把一个流作为返回值,那最终,还是需要RxJava那种针对流处理的Publisher/Subscriber+Callback的方式。 这就是yield的登场了,它没有async/await直观好懂,就不多说了。
顺便转个 JavaScript async/await 函数的含义和用法 - 阮一峰的网络日志,里面也有提到yield,看看就知道了。

真想不到以前弱弱的Java和JavaScript成长到现在这么强大,真真是凝聚着无数高手们的心血,硬是挤得.NET直哆嗦(即使.NET在实现上依然优于Java,但是事儿不是那么单纯的)。真是白让我以前那么喜欢.NET。