SpringBoot2 应用 Axis 1.4 开发 WebService

有了前一篇 应用 Axis 1.4 开发 WebService 的对 Axis 1 较为深刻的理解后,现在正式给古老的 Axis 1.4  拉个伴,那就是 SpringBoot2。SpringBoot2 + Axis 1 的主要工作就是把 Axis 的 web.xml 用 SpringBoot2 的方式进行转述。

在 SpringBoot 中用 Axis 1 后,有两个特性不再支持

  1. 不再支持 jws 即时发布 Web Service,不能直接搬用 url-pattern *.jws,没继续深究,实际中希望这么部署的方式用得较少
  2. 不再支持 SOAPMonitorService,它是一个 Java Applet,  Java Applet 在新版的 JDK 中已被移除,早就不推荐使用了

在 SpringBoot 中配置 Servlet 或 ServletListener 有两种方式

  1. ServletRegistrationBean/ServletListenerRegistrationBean
  2. @WebServlet/@WebListener

spring-boot-starter 引入了 log4j-to-slf4j, jul-to-slf4j, 所以不需要配置 log4j.properties, 需要的话可用 logback.xml 配置日志输出。 阅读全文 >>

mvn 命令上传文件到 Maven 仓库

针对一个 Maven 的 Java 项目,我们执行 mvn deploy 命令时想要把生成的 jar 包上传到 Maven 仓库(本文将使用私有的 Nexus 仓库)中去。所要用到的插件 Maven Deploy Plugin,本文实际就是讲述如何用该插件上传 jar 包到 Maven  仓库,更多用法请参考该插件的官方文档。

本文关键性的两个配置文件是 pom.xml 和 settings.xml。前者配置仓库的地址,后者中配置用户名和密码。要确定 Maven 使用了哪个 settings.xml 文件,用 mvn -X 查看,比如下面的输出

[DEBUG] Reading global settings from /usr/local/Cellar/maven/3.8.3/libexec/conf/settings.xml
[DEBUG] Reading user settings from /Users/yanbin/.m2/settings.xml

Maven 还允许在执行 mvn 命令时用  -s 或 --settings 参数指定 settings.xml 文件,如 mvn deploy --settings settings.xml

所以对于 settings.xml 文件的修改,可修改全局的,用户的或参数 --settings 指定的。 阅读全文 >>

构建 AWS Lambda Python Docker 镜像

AWS 的 Lambda 在 2020-12-01 开始支持用 Docker 镜像存放代码,见 New for AWS Lambda - Container Image Support。AWS Lambda 最初的对发布包的限制是 50M, 解压后(因为执行前需要解压缩)不能超过 250M,对于压缩比小于 1/5 的包来说,要突破 50M 部署包的限制就要用 2018-11-29 推出的层(layer), 即把 Lambda 的依赖可以组织为层,每个 Lambda 可引用最多 5 个层,但最终 Lambda 加上层所解压后的大小仍然有 250 M 的限制。

对于使用了大量依赖的 Lambda,比如 Python 中用了 Pandas 之类的数学分析包,250M 的大小是不够的,所以才有了 Docker 镜像化的 Lambda, 镜像的大小限制一下蹦到 10G,要构建出一个 10G Lambda 用的 Linux 镜像, 那绝对是个巨兽,至少目前是超越我的想像力,除非往里面塞入大量的业务数据。关于 Lambda 有哪些限制,请参阅 Lambda quotas

介绍完 Lambda 引入 Docker 镜像的背景后,本文接下来只关注如何构建一个 Python Lambda 镜像,对于如何部署 Docker 化的 Lambda, 不在本文的范围之内。主要的参考文档为 AWS Lambda 官方的 Deploy Python Lambda functions with container images. 阅读全文 >>

创建和发布自己的 Python 包到 PyPI 上

像 Java 可发布包到 Maven 仓库,NodeJS 发布包到 NPM 一样,我们也可以创建自己的 Python 包并发布到 PyPI 仓库中去。或者内部使用的包,只须发布到私有的 Nexus 服务器上。

本文中的例子将创建一个 Python 包 bounded-executor, 并发布到 PyPI 上。为什么创建这个包呢?原因是直接用 Python 的 ThreadPoolExecutor 或  ProcessPoolExecutor 来提交任务的话,任务的等待队列是没有边界的,这就会造成因提交任务过快而使得内存爆满。本包最为合适的名称应该是 bounded-pool-executor, 可是名字已被他人使用,但此外的实现有所不同,ThreadPoolExecutor 用 Queue(maxsize) 来控制,而 ProcessPoolExceutor 用 BoundedSemaphore 来控制。

我们以经典的 Python 工程目录结构为例,构建的核心是执行 setup.py 中的 setup 函数,由此来理解 setup 的最主要配置与关键命令做了些什么。这样有助于我们理解其他的 Python 包管理工具的底层行为,从中我们可以对比 poetry 的 build, install, 和 publish 命令。 阅读全文 >>

理解 Docker Client/Server 架构, 找寻 Docker Desktop 替代品

本文继上篇 摆脱 Docker Desktop 即将到来的收费 进一步寻找符合自己需求的 Docker Desktop 替代品,前面试用过 hyperkit + minikube, Podman, 最终还是确定了用 docker-machine。之所以选择了它是基于下面几个需求:

  1. 连接 VPN 后 Docker 还要能继续工作 (通过 socket 文件和 localhost 与 Docker Host 通信不惧怕 VPN 连接. 因为 VPN 会接管路由表,所以用 IP 来连接 Docker Host 的话,VPN 连上后将可能无法访问 Docker Host)
  2. 能与 IDE 进行集成开发与调试  (IntelliJ IDEA 能与 Docker Desktop, Docker Machine, TCP socket 和 SSH 上的 Docker Host 集成调试,但无法与 Daemonless 的 Podman 集成)
  3. DOCKER_HOST 能是远程机器 (由于 Podman 设计为 Daemonless,也就没有 Docker Host, 无法进行远程构建)

本文力图更深入的理解 Docker 的架构来解释最后选择的来由,清楚了原理后可以自主创建一个 Docker Host,连 docker-machine 也可以不用。比如创建一个 AWS EC2 实例作为 Docker Host, 然后在本地执行 docker 命令进行镜像的构建与容器的运行,这时候镜像构建过程与容器执行的环境是在 EC2 上,再也不用先把本地的文件上传(scp 或 rsync) 到 EC2 上,然后 ssh  到 EC2 去执行 docker 命令了。

一个小插曲:本人曾经随手在  ~/Downloads 目录下建立一个只有 FROM busybox 一行的 Dockerfile 文件,然后运行 docker build ...  命令,结果每次都提示磁盘空间不足,本机磁盘还非常宽裕,Docker Machine 也分配了 20 G 内存,怎么会不够了呢?登入到 Docker Machine  后 df 确实没空间了。四处找原因,原来是 docker build ... 一执行,不管 3721 首先把当前目录下的所有文件全部拷贝到 Docker Machine 中去,~/Downloads 目录中下了几十个 G 的内容,所以把 Docker Machine 给挤暴掉。解决办法就是要把  Dockerfile 放到一个没有无用文件的独立目录中去,这也是为什么 Dockerfile 中的 COPY 命令只能从当前目录中拷贝文件的原因。 阅读全文 >>

Python 中创建 PostgreSQL 数据库连接池

征战 Java 多年,习惯于使用数据库之前都必须创建一个连接池,即使是单线程的应用,只要有多个方法中需用到数据库连接,建立一两个连接的也会考虑先池化他们。连接池的好处多多,1) 如果反复创建连接相当耗时,2) 对于单个连接一路用到底的应用,有连接池时避免了数据库连接对象传来传去,3) 忘记关连接了,连接池幸许还能帮忙在一定时长后关掉,当然密集取连接的应用势将耗尽连接,3) 一个应用打开连接的数量是可控的

接触到 Python 后,在使用 PostgreSQL 也自然而然的考虑创建连接池,使用时从池中取,用完后还回去,而不是每次需要连接时创建一个物理的。Python 连接 PostgreSQL 是主要有两个包,py-postgresqlpsycopg2, 而本文的实例将使用后者。

Psycopg 在 psycopg2.pool 模块中提供了两个连接池的实现在,它们都继承自 psycopg2.pool.AbstractConnectionPool, 该抽象类的基本方法是

  1. getconn(key=None): 获取连接
  2. putconn(conn, key=None, close=False): 归还连接
  3. closeall(): 关闭连接池中的所有连接

阅读全文 >>

Python 依赖管理与构建工具(CookieCutter, PyScaffold, PyBuilder, Poetry)

Python 历时这么久以来至今还未有一个事实上标准的项目管理及构建工具,以至于造成 Python 项目的结构与构建方式五花八门。这或许是体现了 Python 的自由意志。不像 Java 在经历了最初的手工构建,到半自动化的 Ant, 再到 Maven 基本就是事实上的标准了。其间 Maven 还接受了其他的 Gradle(Android 项目主推), SBT(主要是 Scala 项目), Ant+Ivy, Buildr 等的挑战,但都很难撼动 Maven 的江湖地位,而且其他的差不多遵循了 Maven 的目录布局。

回到 Python,产生过 pip, pipenv, conda 那样的包管理工具,但对项目的目录布局没有任何约定。关于构建很多还是延续了传统的 Makefile 的方式,再就是加上 setup.py 和 build.py 用程序代码来进行安装与构建。关于项目目录布局,有做成项目模板的,然后做成工具来应用项目模板。下面大概浏览一下四个工具的使用

  1. CookieCutter
  2. PyScaffold
  3. PyBuilder
  4. Poetry

阅读全文 >>

创建 AWS EC2 实例时 userdata 的一些知识

我们在初始一个 AWS EC2 实例时,可以通过 user data 让 EC2 第一次启动后做些事情,可以放置 shell script 或 cloud-init 指令。在控制台设置 user data 可用明文文本,由 awscli 创建时可使用一个文件,或者通过 API 用 base64 编码的内容。

下面是 user data 被执行时需知晓的一些知识

  1. 是脚本时必须以 #! 开始,俗称 Shebang, 如 #!/bin/bash
  2. user data是以 root 身份执行,所以不要用 sudo, 当然创建的目录或文件的 owner 也是 root,需要 ec2-user 用户访问的话需要 chmod 修改文件权限,或者直接用 chown ec2-user:ec2-user -R abc 修改文件的所有者()
  3. 脚本不能交互,有交互时必须想办法跳过用户输入,如 apt install -y xzy, 带个  -y 标记
  4. 如果脚本中需访问 AWS 资源,权限由 Instance Profile 所指定的 IAM role 决定
  5. user data 中的脚本会被存储在  /var/lib/cloud/instances/<instance-id>/user-data.txt 文件中,因此也可以从这里验证 user data 是否设置正确。或者在 EC2 实例上访问 http://169.254.169.254/latest/user-data 也能看到 user data 的内容。并且在 EC2 实例初始化后不被删除,所以以此实例为基础来创建一个新的 AMI 需把它删除了
  6. user data 的大小限制为 16 KB, 指 base64 编码前的大小
  7. cloud-init 的输出日志在 /var/log/cloud-init-output.log, 它会捕获 cloud-init 控制台的输出内容

阅读全文 >>

摆脱 Docker Desktop 即将到来的收费

最近本人在 Mac OS X 下安装的 Docker Desktop 经常蹦出要升级的窗口,Skip this update PRO 不能用,Install & Restart  也总是失败,所以每次只能 SNOOZE。原来觉得事有蹊跷,后来才知道这或许与近日吵得沸沸扬扬的 Docker Desktop 收费计划有关。Docker Desktop 是专门为 Windows 和 Mac OS X 定制的,Mac OS X 和 Windows  都是开发人员用的平台。Linux 下可以不用 Docker Desktop,Linux 下 Docker 之间甚至一层窗户纸都没有,实际部署的 Docker 服务也是运行在 Linux 下的。

墙里边微信正在谋划着对聊天记录的云存储收年费,外边是 Docker 在向大公司和开发人员下手,这难道是美国加州版的共同富裕? 阅读全文 >>

如何调试 ECR Docker 镜像

常常因为在 AWS 上部署的 ECS 或 EKS 服务,甚至是使用了 ECR 镜像的 Lambda 服务这样或那样的原因无法启动,或其他莫名的异常,这时候最好能直接调试 ECR 上的 Docker 镜像,比调试用于打包 Docker 的源代码更接近真实环境。

要调试 Docker 镜像需要先从 ECR 中下载到 AWS 服务用的镜像,下面以运行 Java 的 Docker 为例,同时用 IntelliJ IDEA 关联源代码进行远程调试。

从 ECR 下载 Docker 镜像部分可参考 推送 Docker 镜像到 Amazon ECR 仓库, 那篇文章写作之时可能与现在略有不同。具体需直接进到 ECR 的页面,如 https://console.aws.amazon.com/ecr/repositories/private/<aws_account_id>/<ecr_name>?region=<region>,点击 View push commands 可看到用 AWS CLI 如何登陆 ECR,现在看到的在 macOS/Linux 下的命令是(假设 AWS AccountId 是 123456789, region 是 us-east-1)

aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com

假如 ECR 仓库名是 test-java, 那么要下载 tag 1.0.1 的命令是 阅读全文 >>