k8s上使用流水线部署应用

1. 部署流程

  1. 为每一个项目准备一个Dockerfile;Docker按照这个Dockerfile将项目制作成镜像
  2. 为每一个项目生成k8s的部署描述文件
  3. Jenkins编写好Jenkinsfile

2. 抽取生产环境配置

gulimall-cart服务为例

  1. 首先创建application-prod.properties文件,也可以使用yaml,但是我觉得yaml对格式的要求太高了就使用properties

  2. 将之前的yaml文件转为properties文件,再复制到application-prod.properties,此处我使用的在线网站的方式https://www.toyaml.com/index.html

  3. 更换成功后先测试本地环境是否能起来,排查是否有转换上的问题

  4. 再将本地测试的mysql,redis,elasticsearch,nacos,rabbitmq,zipkin,sentinel链接换成线上的域名

  5. 测试成功后再将所有服务的ip做域名替换

  6. 将所有服务的正式环境端口都设为8080或者你喜欢的

    原因:这样的话我们就不需要在部署的时候关注服务本来的端口,服务被打成了镜像,在不同的容器中使用相同的端口是被允许的.而我们访问服务是通过注册中心,只关注服务名.

3. 开通阿里云容器镜像服务

此处设置的密码就是以后的登录密码

创建镜像仓库,选择代码源未本地仓库

3.1 本镜像仓库操作指南

3.1.1 登录阿里云Docker Registry

$ docker login --username=院长大人9 registry.cn-hangzhou.aliyuncs.com

用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。

您可以在访问凭证页面修改凭证密码。

3.1.2 从Registry中拉取镜像

$ docker pull registry.cn-hangzhou.aliyuncs.com/zr-dev/gulimall-dev:[镜像版本号]

3.1.3 将镜像推送到Registry

$ docker login --username=院长大人9 registry.cn-hangzhou.aliyuncs.com
#docker tag镜像打一个新的标签,`registry.cn-hangzhou.aliyuncs.com/zr-dev/`前缀需要与阿里云的一致
#gulimall-dev是一个镜像仓库,就是我之前创建的仓库,可以随意修改,如果推送时没有该仓库,会自动创建
#例如我要打nginx的镜像:docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/zr-dev/gulimall-nginx:[镜像版本
#号],主要将后缀修改即可
$ docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/zr-dev/gulimall-dev:[镜像版本号]
$ docker push registry.cn-hangzhou.aliyuncs.com/zr-dev/gulimall-dev:[镜像版本号]

请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数。

3.1.4 选择合适的镜像仓库地址

从ECS推送镜像时,可以选择使用镜像仓库内网地址。推送速度将得到提升并且将不会损耗您的公网流量。

如果您使用的机器位于VPC网络,请使用 registry-vpc.cn-hangzhou.aliyuncs.com 作为Registry的域名登录。

3.1.5 示例

使用"docker tag"命令重命名镜像,并将它通过专有网络地址推送至Registry。

$ docker imagesREPOSITORY                                                         TAG                 IMAGE ID            CREATED             VIRTUAL SIZEregistry.aliyuncs.com/acs/agent                                    0.7-dfb6816         37bb9c63c8b2        7 days ago          37.89 MB$ docker tag 37bb9c63c8b2 registry-vpc.cn-hangzhou.aliyuncs.com/acs/agent:0.7-dfb6816

使用 “docker push” 命令将该镜像推送至远程。

$ docker push registry-vpc.cn-hangzhou.aliyuncs.com/acs/agent:0.7-dfb6816

4. 创建微服务Dockerfile

#构建的镜像设置基础镜像
FROM java:8
#为构建的镜像设置监听端口
EXPOSE 8080
#指定镜像内的目录为数据卷
VOLUME /tmp
#构建镜像时,复制上下文中的文件到镜像内
ADD target/*.jar  /app.jar
#在镜像的构建过程中执行特定的命令,并生成一个中间镜像
RUN bash -c 'touch /app.jar'
#指定镜像的执行程序
ENTRYPOINT ["java","-jar","-Xms128m","-Xmx300m","/app.jar","--spring.profiles.active=prod"]

4.1 打包镜像推送

当我们手动打包将jar与Dockerfile放同一个目录时,需要修改Dockerfile的ADD target/*.jar 修改目录位置

#jar与Dockerfile放同一个目录时,否则需要修改-f Dockerfile的位置
docker build -f Dockerfile -t docker.io/zr/admin:v1.0 .

打包成功后查看docker镜像

由于我们需要将镜像推送至阿里云镜像,所以我们需要参照阿里云前缀为镜像重新打标签,顺便新建一个gulimall-admin仓库

docker tag 68dd4281cbc0 registry.cn-hangzhou.aliyuncs.com/zr-dev/gulimall-admin:v1.0

标签打成功后发现他们的镜像id都是相同的

最后推送至镜像仓库,推送后自动帮我们创建对应仓库

docker push registry.cn-hangzhou.aliyuncs.com/zr-dev/gulimall-admin:v1.0

5. 创建微服务k8s部署描述文件

5.0 理解targetport,port,nodeport

个人理解:

targetport:容器暴露的端口

port:容器在service中暴露的端口(集群中可访问的端口)

nodeport:容器在服务器中暴露的端口(外网可访问的端口)

以gulimall-auth-server为例,需要部署的所有文件都需要该描述文件并放在各自服务的相同名称目录下

5.1 在服务下新建一个相关部署文件

kind: Deployment
apiVersion: apps/v1
metadata:name: gulimall-auth-servernamespace: gulimalllabels:app: gulimall-auth-server
spec:replicas: 1selector:matchLabels:app: gulimall-auth-servertemplate:metadata:labels:app: gulimall-auth-serverspec:containers:- name: gulimall-auth-serverimage: $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:latestports:- containerPort: 8080protocol: TCPresources:limits:cpu: 1000mmemory: 500Mirequests:cpu: 10mmemory: 10MiterminationMessagePath: /dev/termination-logterminationMessagePolicy: FileimagePullPolicy: IfNotPresentrestartPolicy: AlwaysterminationGracePeriodSeconds: 30strategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%revisionHistoryLimit: 10progressDeadlineSeconds: 600
---
kind: Service
apiVersion: v1
metadata:name: gulimall-auth-servernamespace: gulimalllabels:app: gulimall-auth-server
spec:ports:- name: httpprotocol: TCPport: 8080      #port:容器在service中暴露的端口(集群中可访问的端口)targetPort: 8080  #targetport:容器暴露的端口nodePort: 31000   #nodeport:容器在服务器中暴露的端口(外网可访问的端口)selector:app: gulimall-auth-servertype: NodePortsessionAffinity: None

5.2 在其他服务创建部署文件

在其他服务的相同位置创建对应服务名的yaml文件,我这里是用的[servicename]/deploy/[servicename]-deploy.yaml,将之前的gulimall-auth-server-deploy.yaml复制到目录下改名后需要修改下图内容及nodePort不要有重复(因为之前我们为所有服务的端口都为8080所以不用修改)

nodePort最好在原来的基础上多加几个,给后期集群预留端口

6. Jenkins编写好Jenkinsfile(自定义流水线)

流水线 (jenkins.io)

6.1 k8s创建流水线

设置代理类型node,lable为maven

6.2 流水线第一步–gitee拉取代码

gitee-id

创建码云凭证

对应的Jenkinsfile

pipeline {agent {node {label 'maven'}}stages {stage('拉取代码') {steps {git(url: 'https://gitee.com/zhourui815/gulimall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)}}}
}

6.3 流水线第二步–参数化构建环境变量

作用:

1.可以接受传递进来的参数

2.可以在外面定义参数的值类型

pipeline {agent {node {label 'maven'}}stages {stage('拉取代码') {steps {git(url: 'https://gitee.com/zhourui815/gulimall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)sh 'echo 正在构建 $PROJECT_NAME  版本号:$PROJECT_VERSION 将会提交给 $REGISTRY 镜像仓库'}}}parameters {string(name:'PROJECT_VERSION',defaultValue: 'v0.0Beta',description:'项目版本')string(name:'PROJECT_NAME',defaultValue: 'gulimall-gateway',description:'构建模块')}
}

运行时输入参数

6.4 流水线第三步–sonar代码质量分析

Jenkinsfile

pipeline {agent {node {label 'maven'}}environment {DOCKER_CREDENTIAL_ID = 'alidockerhub'GITEE_CREDENTIAL_ID = 'gitee-id'KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'REGISTRY = 'registry.cn-hangzhou.aliyuncs.com'DOCKERHUB_NAMESPACE = 'zr-dev'GITEE_ACCOUNT = 'zhourui815'SONAR_CREDENTIAL_ID = 'sonar-qube'BRANCH_NAME = 'master'}stages {stage('拉取代码') {steps {git(url: 'https://gitee.com/zhourui815/gulimall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)sh 'echo 正在构建 $PROJECT_NAME  版本号:$PROJECT_VERSION 将会提交给 $REGISTRY 镜像仓库'}}stage('代码质量分析') {steps {container ('maven') {withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {withSonarQubeEnv('sonar') {sh "echo 当前目录 `pwd`"sh "mvn clean install -Dmaven.test.skip=true"sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.branch=$BRANCH_NAME -Dsonar.login=$SONAR_TOKEN"}}timeout(time: 1, unit: 'HOURS') {waitForQualityGate abortPipeline: true}}}}}parameters {string(name:'PROJECT_VERSION',defaultValue: 'v0.0Beta',description:'项目版本')string(name:'PROJECT_NAME',defaultValue: 'gulimall-gateway',description:'构建模块')}
}

由于sonar需要一个mvn-setting文件,其实就是为sonar设置maven镜像仓库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NZKq4JLz-1646796170903)(http://zr.zhourui.site/img/image-20220228160913784.png)]

mvn-setting.xml放在父项目下,根据(sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml)来指定位置

<settings><mirrors><mirror><id>aliyun</id><name>aliyun Maven</name><mirrorOf>*</mirrorOf><url>http://maven.aliyun.com/nexus/content/groups/public</url></mirror></mirrors><profiles><profile><id>jdk-1.8</id><activation><activeByDefault>true</activeByDefault><jdk>1.8</jdk></activation><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion></properties></profile></profiles>
</settings>

登录sonarqube控制台查看http://10.0.0.41:32112/

6.5 流水线第四步–构建镜像&推送快照镜像

配置阿里云镜像仓库凭证

此处我配置阿里云账号与密码

Jenkinsfile

pipeline {agent {node {label 'maven'}}environment {DOCKER_CREDENTIAL_ID = 'alidockerhub'GITEE_CREDENTIAL_ID = 'gitee-id'KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'REGISTRY = 'registry.cn-hangzhou.aliyuncs.com'DOCKERHUB_NAMESPACE = 'zr-dev'GITEE_ACCOUNT = 'zhourui815'SONAR_CREDENTIAL_ID = 'sonar-qube'BRANCH_NAME = 'master'}stages {stage('拉取代码') {steps {git(url: 'https://gitee.com/zhourui815/gulimall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)sh 'echo 正在构建 $PROJECT_NAME  版本号:$PROJECT_VERSION 将会提交给 $REGISTRY 镜像仓库'}}stage('代码质量分析') {steps {container ('maven') {withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {withSonarQubeEnv('sonar') {sh "echo 当前目录 `pwd`"sh "mvn clean install -Dmaven.test.skip=true"sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.branch=$BRANCH_NAME -Dsonar.login=$SONAR_TOKEN"}}timeout(time: 1, unit: 'HOURS') {waitForQualityGate abortPipeline: true}}}}stage ('构建镜像 & 推送快照镜像') {steps {container ('maven') {sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'sh 'cd $PROJECT_NAME && docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,credentialsId : "$DOCKER_CREDENTIAL_ID" ,)]) {sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'sh 'docker push  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'}}}}}parameters {string(name:'PROJECT_VERSION',defaultValue: 'v0.0Beta',description:'项目版本')string(name:'PROJECT_NAME',defaultValue: 'gulimall-gateway',description:'构建模块')}
}

6.6 流水线第五步–部署服务

6.6.1 动态指定模块部署

在部署时无法读取到变量

将英文单引号换成英文双引号,即可读取到变量

Jenkinsfile

     stage('部署到k8s') {when{branch 'master'}steps {input(id: "deploy-to-dev-$PROJECT_NAME", message: '是部署到k8s?')sh 'echo 正在部署 $PROJECT_NAME'kubernetesDeploy(configs: "$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")}}

实现效果

部署文件

gulimall-gateway / deploy / gulimall-gateway-deploy.yaml

kind: Deployment
apiVersion: apps/v1
metadata:name: gulimall-gatewaynamespace: gulimalllabels:app: gulimall-gateway
spec:replicas: 1selector:matchLabels:app: gulimall-gatewaytemplate:metadata:labels:app: gulimall-gatewayspec:containers:- name: gulimall-gatewayimage: $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:latestports:- containerPort: 8080protocol: TCPresources:limits:cpu: 1000mmemory: 500Mirequests:cpu: 10mmemory: 10MiterminationMessagePath: /dev/termination-logterminationMessagePolicy: FileimagePullPolicy: IfNotPresentrestartPolicy: AlwaysterminationGracePeriodSeconds: 30strategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%revisionHistoryLimit: 10progressDeadlineSeconds: 600
---
kind: Service
apiVersion: v1
metadata:name: gulimall-auth-servernamespace: gulimalllabels:app: gulimall-auth-server
spec:ports:- name: httpprotocol: TCPport: 8080      #port:容器在service中暴露的端口(集群中可访问的端口)targetPort: 8080  #targetport:容器暴露的端口nodePort: 31012  #nodeport:容器在服务器中暴露的端口(外网可访问的端口)selector:app: gulimall-auth-servertype: NodePortsessionAffinity: None

6.7 流水线第六步–发布版本(流水线结束)

版本发布

需要配置自己的git相关配置

完整Jenkinsfile

pipeline {agent {node {label 'maven'}}stages {stage('拉取代码') {steps {git(url: 'https://gitee.com/zhourui815/gulimall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)sh 'echo 正在构建 $PROJECT_NAME  版本号:$PROJECT_VERSION 将会提交给 $REGISTRY 镜像仓库'container('maven') {sh 'mvn clean install -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml'}}}stage('代码质量分析') {steps {container('maven') {withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {withSonarQubeEnv('sonar') {sh 'echo 当前目录 `pwd`'sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.branch=$BRANCH_NAME -Dsonar.login=$SONAR_TOKEN"}}timeout(time: 1, unit: 'HOURS') {waitForQualityGate true}}}}stage('构建镜像 & 推送快照镜像') {steps {container('maven') {sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'sh 'cd $PROJECT_NAME && docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD' ,usernameVariable : 'DOCKER_USERNAME' ,credentialsId : "$DOCKER_CREDENTIAL_ID" ,)]) {sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'sh 'docker push  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'}}}}stage('推送最新镜像') {when {branch 'master'}steps {container('maven') {sh 'docker tag  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:latest 'sh 'docker push  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:latest '}}}stage('部署到k8s') {when{branch 'master'}steps {input(id: "deploy-to-dev-$PROJECT_NAME", message: '是部署到k8s?')sh 'echo 正在部署 $PROJECT_NAME'kubernetesDeploy(configs: "$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")}}stage('发布版本'){when{expression{return params.PROJECT_VERSION =~ /v.*/}}steps {container ('maven') {input(id: 'release-image-with-tag', message: '是否发布当前版本?')sh 'docker tag  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION 'sh 'docker push  $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION'withCredentials([usernamePassword(credentialsId: "$GITEE_CREDENTIAL_ID",passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {sh 'git config --global user.email "2437264464@qq.com" 'sh 'git config --global user.name "eric_zhou" 'sh 'git tag -a $PROJECT_NAME-$PROJECT_VERSION -m "$PROJECT_VERSION" 'sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@gitee.com/$GITEE_ACCOUNT/gulimall.git --tags --ipv4'}}}}}environment {DOCKER_CREDENTIAL_ID = 'alidockerhub'GITEE_CREDENTIAL_ID = 'gitee-id'KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'REGISTRY = 'registry.cn-hangzhou.aliyuncs.com'DOCKERHUB_NAMESPACE = 'zr-dev'GITEE_ACCOUNT = 'zhourui815'SONAR_CREDENTIAL_ID = 'sonar-qube'BRANCH_NAME = 'master'}parameters {string(name: 'PROJECT_VERSION', defaultValue: 'v0.0Beta', description: '项目版本')string(name: 'PROJECT_NAME', defaultValue: 'gulimall-gateway', description: '构建模块')}
}

最终效果

git上有对应的标签版本,镜像仓库中也会有对应的版本,并且最新的版本也是该版本

7. 读取远程代码中的流水线部署

7.1 第一次执行参数输入不显示,报错问题

当我们运行分支时需要填写参数,如下图但第一次运行不会弹出来

原因:因为我们输入参数是在拉取代码之前,还没有拉取到代码,Jenkinsfile中的参数配置自然没有办法生效

解决:只需要在第一次执行后拉取代码步骤后执行后,再次运行即可

k8s上使用流水线部署应用相关推荐

  1. 如何在两个k8s上使用kubefate部署fate集群?

    本文作者系VMware中国研发中心研发工程师 马陈龙 目标 本文将介绍如何使用kubefate在两个kubernetes集群上部署互通的两个FATE.这两个FATE可以完成各种联邦学习的任务. 完成后 ...

  2. 在云效平台实现流水线部署遇到的问题及解决

    前言:在云效平台上实现流水线部署作为本次大作业中部署工作一项重点,由我在13日和14日两天做了数次尝试并最终得以解决. 7月13日主要解决了项目在服务器上手动部署的问题: 在13日初步使用Python ...

  3. [Kubernetes] 在K8S上部署MySQL 8.0并数据持久化

    在K8S上安装MySQL 1.创建PV apiVersion: v1 kind: PersistentVolume metadata:name: model-db-pv spec:storageCla ...

  4. flink在k8s上的部署和使用教程

    官网:https://ci.apache.org/projects/flink/flink-docs-stable/dev/stream/python.html 架构 要了解一个系统,一般都是从架构开 ...

  5. 通过helm在k8s上部署spark(伪集群版)

    全栈工程师开发手册 (作者:栾鹏) 架构系列文章 首先要求你的k8s支持helm.阿里云自带的k8s已经包含了对helm的支持.关于服务器k8s的部分这里不讨论,我们考论如何用一个已经好的k8s来进行 ...

  6. 在K8s上轻松部署Tungsten Fabric的两种方式

    第一种:在AWS的K8s上部署TF 首先介绍下如何在AWS上使用Kubernetes编排的Tungsten Fabric集群部署沙盒,15分钟就可以搞定.Tungsten Fabric集群由部署节点. ...

  7. 在K8s上部署Redis 集群

    一.前言 架构原理:每个Master都可以拥有多个Slave.当Master下线后,Redis集群会从多个Slave中选举出一个新的Master作为替代,而旧Master重新上线后变成新Master的 ...

  8. Jenkins在k8s上部署

    1.在rancher上搭建jenkins的master镜像,这个可以在官方dockerhub镜像上做修改(harbor.dev.cn/library/jenkinsci/jenkins:2.138.2 ...

  9. GitLab通过CI/CD 实现流水线部署(演示主要是通过shell上传SpringBoot项目)

    GitLab通过CI/CD 实现实现流水线部署(演示主要是通过shell上传SpringBoot项目) 环境准备 1.JDK: 2.maven: 3.Git 4.Docker (本次安装没有使用到,仅 ...

最新文章

  1. OpenCL,OpenGL编译
  2. 理解系统底层的概念是多么重要
  3. LeetCode 375. Guess Number Higher or Lower II
  4. 鸿蒙系统手机用户体验,鸿蒙系统真的来了!用户体验流畅度远超安卓,任正非扳回一城!...
  5. 【转】Asp.net MVC Comet推送
  6. 端午小长假--前端基础学起来02与浏览器交互,表单标签
  7. django-后台管理-控件相关
  8. inode索引节点---初识
  9. 实战解析丨如何对Mysql连接请求的tcpdump内容进行分析
  10. Neo4j从mysql读取数据_[bigdata-086] python3+neo4j 从mysql数据库读取记录然后创建节点和关系写入到neo4j...
  11. Scrapy框架实现持久化存储
  12. 台式计算机开机黑屏,台式电脑开机黑屏只有一个点怎么处理?
  13. 转:iris数据集及简介
  14. matlab求arma模型残差,求教关于ARMA模型的残差检验
  15. Textpattern Solutions: PHP-Based Content Management Made Easy
  16. html5教程_最好HTML和HTML5教程
  17. 分享一张职场学习必备的工作法思维导图
  18. 【干货】Android实现支付宝当面付
  19. linux线程篇,linux线程篇 (二) 线程的基本操作
  20. css 对checkbox样式进行修改

热门文章

  1. Windows下的ARP命令
  2. 关于启发式算法、元启发式算法以及超启发式算法的理解
  3. iOS 各种技术点网址
  4. SpringBoot:异步 定时 邮件任务
  5. 最全最详细的PHP面试题(带有答案)
  6. eNSP实验三:OSPF路由协议
  7. 最小二乘法线性拟合和2次曲线拟合算法
  8. 使用Alexnet实现CIFAR10数据集的训练
  9. 安装和卸载 MS SQL Server 2012数据库
  10. 视频教程-红孩儿网狐Cocos经典棋牌开发教程-手游开发