如果你不幸的点到了这个文章,那个,这是给我自己看的,我记忆力一直在减退:
10岁以前还能背诵唐诗300首;
10岁以后能记住100多物理、化学、数学公式;
20几岁,能记住数学分析7大定理;
30几岁,能记住为数不多的几个敏捷方法论和实践;
40几岁,我开始担心,这样下去记忆力极具下降,这,这不行啊。觉得有必要将一些“不常用”的记忆暂存在这里,希望“简书”还能撑上30年。。。
====== 以下的你看完了如果觉得有用,保存这个笔记,共享记忆给你 =====
2018.3:群晖NAS设置SSH
自己折腾过多个家用NAS的自建以后,去年买了群晖,鉴证了“硬件方案永远比软件方案强万倍”。昨天晚上持续的连接不稳定,群晖的UI不足以定位问题,只能ssh后,自己弄。
问题解决以后忽然感悟:这就是一个不关机的Linux服务器,只用作NAS太浪费了。。。
今天早上,开始安装MySql,Java,做数据库迁移,终于把股票抓取、分析的程序弄上去了,以后再也不用隔三差五的自己手工启动程序抓了。
群晖盒子上面一直放着一个Raspberry Pi,曾经像做“魔镜”来着的,后来一直没折腾了,为什么不拿它做一个Jenkins呢?这样每次改股票代码、编译以后,就不用scp到群晖了。于是安装了Raspbian server。
至此一切顺利和美好,直到“设定publickey给群晖,以便Pi能免密码登录(才好scp要部署的文件)”,首先是“设定了跟没设定一样,还是问密码”;手工sshd -d和ssh -vvv以后,发现Pi这边是 “ssh receive packet: type 51” (这是一个Server端返回的publishkey认证错误),群晖这边是:“Failed publickey for steve from 192.168.0.9 port 33492 ... ssh2: RSA SHA256”。
好吧,上面是背景情况,下面是“记忆”:
https://forum.synology.com/enu/viewtopic.php?t=126166
为了防止群晖论坛挺不过30年,这是一些简述:
根本不是Rasbian的问题,尽管它也有好多ssh的问题,但是这个真的是群晖自己在建立用户目录的时候,瞎弄目录权限。你就得改过来:
* sudo chmod 755 /volume1/homes/someuser
* sudo chmod 700 /volume1/homes/someuser/.ssh
* sudo chmod 644 /volume1/homes/someuser/.ssh/authorized_keys
剩下的都是publickey/privatekey的标准动作。
2018.3:Raspberry PI 安装Jenkins
谁能想到,安装Jenkins又花了将近一个下午,教训是:
Raspbian使用 apt-get install oracle-java8-jdk 安装Java的时候,默认安装的是8u65,而Jenkins在某一个版本(2.0?)开始使用https://letsencrypt.org/的服务给插件更新的服务提供SSL,这样一来,访问插件更新网站就需要一个证书了(回调安装时),而Oracle Java在8u101版本以后才支持letsencrypt,这就会在插件更新的时候报错:SunCertPathBuilderException、PKIX path building failed,别试图禁用什么SSL降低安全性来解决,也不要自己用keytool增加认证,都失败了。唯一的路是安装一个大于101的版本。(这是letsencrypt的支持列表)
卸载已经安装的8u65
sudo apt-get remove --purge oracle-java8-jdk openjdk-7-jre oracle-java7-jdk openjdk-8-jre
没有精神再折腾openjdk了,所以不选择安装openjdk,还是要Oracle的,需要临时设定一个安装源,缺省的只又8u65,通过这个看:
apt-cache policy oracle-java8-jdk
果然没有吧?下面这三个命令安装了一个源:
sudo su
echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main" | tee /etc/apt/sources.list.d/webupd8team-java.list
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
最后一个命令是,给上面的源一个签名,以便作为“官方”源被安装(默认的规则是:不允许安装第三方源的软件),运行的时候,立刻报错:
gpg: failed to start the dirmngr '/usr/bin/dirmngr': 没有那个文件或目录
随即安装dirmngr:
sudo apt install dirmngr
然后就好了,可以签名了,可以安装Java了,可以重新安装Jenkins了,安装Jenkins还有一个坑,官方默认的是低版本1.57,最新的是2.111 Beta版和稳定版2.07,按照下面的方法安装:
wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins -y
安装2.111,然后访问,一切正常了。对了,会有一些安装插件失败的提示,常规动作解决(反复安装几遍),不要自作聪明的删除一些“没用”的插件,Jenkins没到那个聪明程度会告诉你依赖关系,所以不小心你就删了一个插件的依赖,这个插件就安装失败了,之所以要安装几遍就好了,是因为这些新安装的插件也会有依赖关系,安装几遍的结果是每次失败的逐渐减少,最后全部成功。
2018.3: Gradle引入自己/罕见Jar
能想到,让项目编译又花了半个晚上么?也是怪我懒,股票程序一直没有上Jenkins,这个问题是今天才发现的。啥问题呢?股票程序引用了两个第三方jar文件,做科学计算的,以前都是在.m2目录的repositories里面做一个目录,骗maven的,但是这招用在jenkin上,怎么都不行,由于jenkins是root启动的,起初怀疑是是不是目录上传错了地方,就sudo su了一下,传到了root的.m2下,手工运行maven(以root),一切正常。可以在Jenkins还是报错!
查了一下,原来Jenkins的.m2是在/var/lib/jenkins/.m2,不是走~/.m2,尝试修改settings.xml,指定.m2位置,然后在Jenkins里面指定这个settings.xml,结果还是不行。
情急之下用了粗鲁的方法,直接用目录引用jar文件就行了,比如:
<groupId>steve</groupId>
<artifactId>jsc</artifactId>
<version>1.0</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${project.basedir}/lib/jsc.jar</systemPath>
终于编译通过了!
不过有一个警告,说是不建议引用的jar在workspace目录里面,下一个maven版本可能会不允许这样,强迫症的劲头又上来了,换方法!
《plugin》
《groupId》org.apache.maven.plugins《/groupId》
《artifactId》maven-install-plugin《/artifactId》
《version》2.5.2《/version》
《executions》
《execution》
《id》install-jsc《/id》
《phase》clean《/phase》
《configuration》
《file》${basedir}/lib/jsc.jar《/file》
《repositoryLayout》default《/repositoryLayout》
《groupId》steve《/groupId》
《artifactId》jsc《/artifactId》
《version》1.0《/version》
《packaging》jar《/packaging》
《generatePom》true《/generatePom》
《/configuration》
《goals》
《goal》install-file《/goal》
《/goals》
《/execution》
《/executions》
《/plugin》
增加plugin,在编译以前现install一个临时的。
终于优美的解决了。
2018.8:Camunda和Apache NIFI
Camunda是一个工作流,负责“大”业务工作流;NIFI是一个ETL工具,负责“小”技术流;
典型的Camunda应用是:从一个Form开始(不管是谁提交的),经过层层审批后,入库;从这个角度看,Camunda是一个数据收集工具;
典型的Apache NIFI应用是:当一个请求(或者要求)发送过来后,数据经过层层处理、转换,最后显示在页面上;从这个角度上,NIFI是一个数据转换工具;
另一个NiFI的应用场景是:从一个请求开始,数据经过层层转换,最终保存在一个地方;从这个角度看,NIFI除了不支持人工节点,其余的和Camunda一样。
看一个完整的流程(交房产税):
验证用户是否为房主(通过查询n个表确定) -> 显示房产税金额 (通过查询表和写程序计算) -> 提交“交款意愿”(用户确定交款,或者有申诉什么的)-> 政府部门审批 (可能回答问题以后转会用户) -> 用户使用第三方支付接口交款 -> 政府验证是否已经收到款 -> 完毕
这个流程可以分为前半段和后半段,在提交“交款意愿”的Form以前,用NIFI,设定流程(谁知道以后的流程和计算方式会不会有变化?如果有,程序不用变,只需要修改NIFI配置就行);从提交“交款意愿”的Form开始,用Camunda,一直到结束(同样,如果以后审批流程有变化,也不用修改程序)。
2018.8:Camunda的基本使用和怎么使用
参见这个Quick Start,就能对工作流(包括带有人工审批)有大致的了解,说几个这里面没有的:
1、在Service类型的节点中指定Implementation是External,并且给一个Topic,这个Topic的String和写Java代码实现这个External Task Client的subscribe(Topic)对应着;
2、lockDuration是干什么的?为了避免多个客户端处理同一个任务,当一个客户端拿到以后,锁定的时间,默认20分钟。
3、从Moduler的GUIDeploy要是失败了,看Tomcat下面的catalina.out就知道因为什么。大多数情况是由于模型有问题,部署不上去;
4、定义Form的时候,Form Id不能写,否则会被当成External Form;正常情况下,定义了Field的form会直接在TaskList web页面中的Form下看直接显示;
5、有关怎么显示Form让用户填。Camunda提供四种方式显示Form,不过我都觉得不够灵活,还特别破坏架构美感,最终我觉得直接把需要的额数据Post给Camunda的REST API比较好,也就是说,自己写一个Form(不管在Web还是Mobile),爱写多花哨就写多花哨,不管怎么花,数据肯定要提交上来吧,把数据拼成Camunda能认的Json,当作data post给Camunda的Rest Api,完成这个User节点的工作,比如
curl --request POST \
--url http://192.168.0.24:8080/engine-rest/task/7e2ff9bb-a550-11e8-bd95-00155d590513/submit-form \ //这段是REST API
--header 'content-type: application/json' \
--data '{ //以下是POST过去的Data
"variables": {
"item": {
"value": "Computer"
},
"amount": {
"value": 10000,
"type":"long"
}
}
}'
"submit-form" 这个Api就是接受数据,然后标记“任务完成”。其他的Api,看这里
以上是基本使用
以下是怎么用,或者说,如何搭建一个强壮的可扩展应用。
还是拿收房产税这个事情,假定一个场景,这个平台需要满足下面的两个条件(为了简单起见,忽略上文说的NIFI的部分,只说后半部分):
1、支持Web和Mobile,老百姓可以提交;
2、三个政府部门涉及到审批,各个部门需要把信息保存在自己的数据库一份;
分三块:
1、部署camunda Server。使用Springboot引用Canunda的依赖,自己做一个Camunda Server(不用war和Stand along方式),具体参考这里,需要考虑:
A、配置数据库(别用自带的H2)
B、其他参数的配置(比如Admin用户名密码以及自定义UI等)
C、考虑灾备服务器和负载均衡,可以查一下Camunda Cluster的信息
D、初始的业务流程放在指定目录下(启动就加载),然后想好策略,怎么更新(增加、删除)这些业务流程
这个东西当作 Microservice的一个节部署在K8s下面(一份或者两份),并且设定保证活着;
2、做前端的API,支持Web和移动端(为了简单起见,Web和Mobile都不包括在下面的描述中);用Tomcat + Jersey的Spring Boot构建大框架,在这个程序中向Camunda Server(上面那个)发请求,这些请求包括:启动一个流程、列出任务、查看任务状态等等。看看这个会有启发怎么弄。在这部分,考虑一个事情就行:考虑如何将Camunda的任意一个业务流程都能够使用同一套代码兼容,实现:
A、对于不同的业务流程不用修改这里的代码
B、修改业务流程不需要动这里的代码
C、增加业务流程不需要动这里的代码
D、当有了新的流程以后,自动能认,前端只要按照一个名字,就能启动各种流程。可以考虑使用ConfigHub保存对应关系,把要启动的流程(人能看懂)和流程的定义文件(bpmn文件)关联起来
这部分做多个“副本”放在K8s下面,根据网站/移动设备请求使用负载均衡,能够Auto Scaling;
3、写各个节点的Service和User Node,这里分成两种情况
A、不需要Form的(Service Node),比如一个Service节点。可以满足上面说的:各个部门都要保存在自己的数据库。在流程中首先加入一个Service Node,然后做这个Node的监听,收到以后,就写库。由于政府有三个部门参与,就写三个Micro Service,每个针对一个部门,每个MS监听多个Service Node;这三个MS部署n个在K8s下面,根据流量自动或者手动增减。
B、需要Form的(User Node),上面说了,每一个部门写一个MS,除了作为Camunda的External Task Client之外,谁说不能接受一般请求呢?都是基于Spring boot结构的,每一个Form写一个Controller呗。Controller接收到Json数据(前端Api Post过来的),做验证(可能还有处理)以后,当作data转提交给Camunda REST API,完成这个流程节点。对于需要Form的这种情况,如果部门的“事儿”不多,可以让前端API直接调用Camunda的Rest Api。从结构上说,部门级别的处理,应该都在部门的MS里面,由于前端Api是“公用”的,所以不应该包含某一个部门的业务逻辑在里面,也就是说,如果前端Api只管启动一个流程、发送Json数据给某一个User节点,根本不需要要知道这是哪个部门的。
2018.9: dotnet半日游
突然要接手一个,net项目,对于我这个Java阵营的人来说,虽然不恐惧,但是仍然有些陌生,用了大半天得时间,学到一些基本得东西,希望下次再遇到dotnet得时候,别全忘干净。
第一部分:概念
- C#和.net:c#是语言,.net是框架,实际上C#是微软为了让码农爱上dotnet而开发得一套类似Java得语言。所以当别人问你是用.net还是C#开发?你就可以抽他一下。
- .net framework和.net core:framework只能再windows平台使用,每一个windows操作系统都自带一个某版本的framework(比如windows 10自带4.7);core是微软为了进军其他的操作系统而建立的,有点儿类似jvm;说起历史,其实framework也是在底层硬件的基础上封装的一层,有了这个以后,一些闲人觉得在其他平台也要有,比如mono、Xamarin等,于是他们就开始自己开发基于不同操作系统的dotnet底层实现,然后微软觉得不能让你们瞎搞,所以收购了一些公司出了dotnet core这个“JVM”,但是仍然不能阻止闲人瞎搞的步伐,所以为了防止碎片化,微软出了一个standard,dotnet standard,就是说“你们可以搞,但是必须按照标准搞,别乱搞”。而后,就有了各种版本的dotnet实现和standard的对应关系。总之,frameworks虽然只能在windows环境下运行,但是他集成了很多windows的功能(DLL),WCF、WPF什么的都可以用;core虽然可以跨平台,但是有一些功能不支持,毕竟好多windows下面的dll在linux/mac上没有;如果没有其他的特殊要求,用微软自己的dotnet core就好了,别用其他的实现了(这个文章对比了几个dotnet的实现)。对了,微软还把dotnet core开源了(别人瞎搞都开源了,自己不开源推不出去啊)。这个文章讲的比较清楚。
- runtime和SDK:既然是虚拟机那一套么,所以必然和Java一样,又java runtime和Java sdk。如果要开发的话,就得装SDK。
第二部分:环境和开发
- 在Ubuntu上搭建dotnet开发环境:这个文档说了大致的步骤,注意有一个坑人的地方,人家说支持18.04、16.04,没说支持18.10和16.10哈,想当然的在16.10搭建的时候,当然出问题了,下面说一下步骤:
A、先装这个:libicu55(在这儿下载),否则后面会有问题;下载完了以后:dpkg -i libicu52_52.1-3ubuntu0.8_amd64.deb
B、安装key和依赖:
wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get install apt-transport-https
C、按照这个顺序装(不按这个顺序会依次提示你:先装这个,先装那个的):可以先sudo su,
apt-get install dotnet-runtime-deps-2.1
apt-get install dotnet-runtime-2.1
apt-get install dotnet-sdk-2.1
D、用dotnet --version验证是否成功了
- Docker和微软平台:有了docker以后,在linux世界如鱼得水,微软的windows得要license,所以非常遭唾弃,于是微软就做了一个windows core这么个玩意,实际上就是一个只有命令行的windows,在此之上,又有了dotnet的docker images,并且微软自己维护Repo(原本计划着在docker上编译甚至debug,但是在windows上都没有编译成功呢)
- 开发工具:见识过vs studio小50G的安装以后,再也不想装这个开发工具了,见过大的,没见过和游戏一样大的IDE。另外一个原因是vs stidio只能在windows上,Ubuntu没有,看了一些以后,有下面的几个选择:
A、rider(Ubuntu可用),这个是和Intellij一个公司的产品,这个IDE是从给vsstudio做插件起步,然后自己做了这么一个。说起插件,就是Resharper,据说装了以后,vs studio就和和Intellij的Java IDE一样好了
B、VS Code(Ubuntu可用),这是一个好东西,根本上说,他不是一个IDE,而是一个编辑器,和nodepad++, editplus竞争的,但是就是太出色了,所以成为了前端开发工程师的首选,写个Angular妥妥儿的,装了dotnet插件以后,凑活能用吧,语法补全、自动编译什么的都行;这有一个开发、调试设置的文档,这儿还有一个,貌似更全面。(这是官方的文档,主看这个)
C、Mono,这个起初就是在Linux平台用的,有了Rider,这个就不考虑了;
- 编译:在Ubuntu上,使用dotnet命令就可以打包、编译。比如dotnet build。
- 确定自己安装了哪些dotnet环境:打开注册表:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full,看Release,对应下面的表:
第三部分:写代码
- 这是微软的自学成才教程
- 这个Repo可以下载多个例子,到例子下面的目录中,直接dotnet build可以编译
2018.9:在Ubuntu的下使用.net的sqlite数据库
在windows环境下使用sqlite特别易如反掌,在nuget下面配好就行,用
System.Data.SqLite,这个是“空包”也就是说,他是几个包的引用,这几个包是:
System.Data.SqLite.Core, System.Data.SqLite.EF6, System.Data.SqLite.Linq
然后就可以了。在Linux下本想也是这么简单,但是出现了下面的这个错误:Unable to load DLL ‘SQLite.Interop.dll’,找不到这个文件。看了Debug目录下,的确有这个dll(在x86和x64下面都有),然后把它拷贝到Debug目录下也不行。
在网上找到,原来是需要在本地环境编译一把SqLite,由于懒得干编译,想想要安装GCC环境就难受,于是尝试了在网上能找到的全部其他方法,
无一能用
所以,就别浪费时间了,编译吧,具体步骤在这个帖子里,然后拷贝到Debug目录下。
(还想到一个偷懒的方法,想直接下载一个ubuntu16.4的编译好的,结果哪儿都没有)。