zoukankan      html  css  js  c++  java
  • k8s入坑之路(13)服务迁移(定时任务 微服务 传统服务)

     

    定时任务迁移kubernetes

    服务迁移步骤

    1.安装好java

    2.安装好maven

    • 项目打包
      mvn package
    • 测试传参运行
      java -cp cronjob-demo-1.0-SNAPSHOT.jar com.mooc.demo.cronjob。Main
    • 编辑Dockfile
      FROM 172.17.166.172/kubenetes/openjdk:8-jre-alpine
      
      COPY target/cronjob-demo-1.0-SNAPSHOT.jar /cronjob-demo.jar
      
      
      ENTRYPOINT ["java", "-cp", "/cronjob-demo.jar", "com.mooc.demo.cronjob.Main" ]
    • 打包并运行测试镜像
      docker build -t cronjob-demo:v1 .
      docker run -it cronjob-demo:v1
    • 修改镜像tag并上传
      docker tag cronjob-demo:v1 172.17.166.17/kuberneres/cronjob-demo:v1
      
      docker push 172.17.166.17/kuberneres/cronjob-demo:v1
    • 制作k8s部署文件
      apiVersion: batch/v1beta1
      kind: CronJob
      metadata:
        name: cronjob-demo
      spec:
        schedule: "*/1 * * * *"  #分时日月周
        successfulJobsHistoryLimit: 3 #成功任务历史保存个数
        suspend: false    #是否停止 如果是true cronjob并不会调度起来
        concurrencyPolicy: Forbid #并行策略
        failedJobsHistoryLimit: 1 #失败保存个数
        jobTemplate:
          spec:
            template:
              metadata:
                labels:
                  app: cronjob-demo
              spec:
                restartPolicy: Never #重启策略 
                containers:
                - name: cronjob-demo
                  image: 172.17.166.172/kubenetes/cronjob:v1
    • 查看任务
      kubectl apply -f conjob-demo.yaml
      kubectl get cronjob

    【不熟悉SpringBoot的筒子看过来】SpringBoot快速入门

     简介

    SpringBoot使你可以非常容易的创建一个独立的、生产级的、基于spring的应用。
    它大量简化了使用spring带来的繁琐的配置,大部分基于SpringBoot的应用只需要一点点的配置。

    特征

    • 独立的spring应用(内置tomcat、jetty,无需部署war包)
    • 提供了丰富的"starter"依赖,简化应用构建配置
    • 自动配置spring和第三方依赖库
    • 没有代码生成,没有xml配置
    • 提供准生产功能,如指标,健康检查和外部配置

    Quick Start

    生成项目

    访问官网:https://start.spring.io/
    选择构建工具,如:Maven Project、Java、Spring Boot 版本 2.1.4 以及一些基本信息,如下图:

    最终会下载到一个demo.zip,解压后主要目录结构如下

    ├── demo
    │   ├── pom.xml
    │   └── src
    │       └── main
    │           ├── java
    │           │   └── com
    │           │       └── example
    │           │           └── demo
    │           │               └── DemoApplication.java
    │           └── resources
    │               └── application.properties

    在demo基础上做一个web服务

    改造后的pom
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>demo</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    View Code
    服务配置 - application.properties
    # 服务名
    server.name=springboot-web-demo
    # web服务监听端口
    server.port=8080
    增加controller代码

    com.example.demo.DemoController.java

    package com.example.demo;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class DemoController {
    
        @RequestMapping("/hello")
        public String sayHello() {
            return "Hello SpringBoot";
        }
    
    }
    运行&测试

    经过以上步骤,一个基于springboot的web服务就搭建好了。

    运行方式如下:

    • 在IDE中:
      直接以DemoApplication做为启动类。
    • 在命令行下:
    # 构建fatjar(构建结果在target目录下)
    $ cd demo
    $ mvn clean package
    
    # 运行jar包
    $ java -jar target/demo-0.0.1-SNAPSHOT.jar

    测试:
    打开浏览器访问: http://localhost:8080/hello 看看效果吧

     

    springboot的web服务迁移kubernetes

    • 打包
      mvn package
    • Dockerfile编写
      FROM 172.17.166.172/kubenetes/openjdk:8-jre-alpine
      
      COPY target/springboot-web-demo-1.0-SNAPSHOT.jar /web-demo.jar
      
      
      ENTRYPOINT ["java" , "-jar" , "/web-demo.jar"]
    • build镜像 测试并上传镜像
      jar -tf springboot-web-demo-1.0-SNAPSHOT.jar #查看jar包中包含的内容

      java -jar springboot-web-demo-1.0-SNAPSHOT.jar #测试包运行是否正常
      docker build -t springboot-web-demo:v1 . 

      docker run -it springboot-web-demo:v1

      docker tag springboot-web-demo:v1 172.17.166.217/kubernetes/springboot-web-demo:v1

      docker push springboot-web-demo:v1 172.17.166.217/kubernetes/springboot-web-demo:v1
    • 编辑k8s部署文件并运行
      #deploy
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: web-demo
      spec:
        selector:
          matchLabels:
            app: springboot-web-demo
        replicas: 2
        template:
          metadata:
            labels:
              app: springboot-web-demo
          spec:
            containers:
            - name: springboot-web-demo
              image: 172.17.166.217/kubenetes/web:v1
              ports:
              - containerPort: 8080
      ---
      #service
      apiVersion: v1
      kind: Service
      metadata:
        name: springboot-web-demo
      spec:
        ports:
        - port: 80
          protocol: TCP
          targetPort: 8080
        selector:
          app: springboot-web-demo
        type: ClusterIP
      
      ---
      #ingress
      apiVersion: networking.k8s.io/v1
      kind: Ingress
      metadata:
        name: springboot-web-demo
      spec:
        rules:
        - host: www.cssp.com
          http:
            paths:
            - pathType: Prefix
              path: /
              backend:
                service:
                  name: springboot-web-demo
                  port:
                    number: 80
      spring-web-demo.yaml
      kubectl apply -f spring-web-demo.yaml
      
      kubectl get deploy spring-web-demo
      
      kubectl get pod -l app.kubernetes.io/name=spring-web-demo

    Dubbo快速入门

    简介

    Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

    Dubbo源自阿里巴巴,2018年初贡献给了apache基金会。已经经历两年多的孵化。
    据悉,2.7.x会作为Dubbo在Apache社区的毕业版本,Dubbo将有机会成为继RocketMQ后,来自阿里巴巴的又一个Apache顶级项目(TLP)。

    架构

    dubbo主要有三种角色:

    • 服务的提供者
      启动后会把服务的信息写入注册中心(服务的ip地址,端口,有哪些接口等)
    • 服务消费者
      访问注册中心找到服务提供者的信息,并跟服务提供者建立连接。
    • 注册中心
      主要作用是存储服务的信息,并对服务的变化做通知。

    Quick Start

    最常见的使用dubbo的方式是基于spring框架。下面的内容也是基于spring框架的配置去演示如何开发一个基于dubbo的应用。

    首先我们创建一个根目录叫:dubbo-demo:

    $ mkdir dubbo-demo
    $ cd dubbo-demo

    然后在根目录下创建三个子目录:

    • dubbo-demo-api: 服务的api定义
    • dubbo-demo-provider: 服务提供者
    • dubbo-demo-consumer: 服务消费者

    1. 注册中心 - zookeeper

    dubbo常用的注册中心是zookeeper,首先用docker启动一个zookeeper服务,暴露出2181端口。

    docker run -idt -p 2181:2181 zookeeper:3.5

    2. dubbo-demo-api - 服务接口定义

    定义服务接口(DemoService.java)

    package org.apache.dubbo.demo;
    
    public interface DemoService {
        String sayHello(String name);
    }

    此时工程的结构应该类似这样:

    ├── dubbo-demo-api
    │   ├── pom.xml
    │   └── src
    │       └── main
    │           └── java
    │               └── org
    │                   └── apache
    │                       └── dubbo
    │                           └── demo
    │                               └── DemoService.java

    3. dubbo-demo-provider - 服务提供者

    服务实现类(DemoServiceImpl.java)
    package org.apache.dubbo.demo.provider;
    import org.apache.dubbo.demo.DemoService;
    
    public class DemoServiceImpl implements DemoService {
        public String sayHello(String name) {
            return "Hello " + name;
        }
    }
    服务启动类(Provider.java)
    package org.apache.dubbo.demo.provider;
    
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class Provider {
    
        public static void main(String[] args) throws Exception {
            System.setProperty("java.net.preferIPv4Stack", "true");
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
            context.start();
            System.out.println("Provider started.");
            System.in.read(); // press any key to exit
        }
    }
    通过spring配置暴露服务(provider.xml)
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
           http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
        <!-- 服务提供者的应用名 -->
        <dubbo:application name="demo-provider"/>
        <!-- 把服务注册到zookeeper -->
        <dubbo:registry address="zookeeper://${zookeeper_ip_addr}:2181"/>
        <!-- 使用dubbo协议暴露服务端口20880 -->
        <dubbo:protocol name="dubbo" port="20880"/>
        <!-- 服务的实现类 -->
        <bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
        <!-- 声明要暴露的服务接口 -->
        <dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>
    </beans>
    配置日志(log4j.xml)
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
        <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
            <param name="encoding" value="UTF-8"/>
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] {%p} %c %L - %m%n" />
            </layout>
        </appender>
        <root>
            <level value="warn" />
            <appender-ref ref="stdout" />
        </root>
    </log4j:configuration>
    最终项目结构如下
    ├── dubbo-demo-provider
    │   ├── pom.xml
    │   └── src
    │       └── main
    │           ├── java
    │           │   └── org
    │           │       └── apache
    │           │           └── dubbo
    │           │               └── demo
    │           │                   └── provider
    │           │                       ├── DemoServiceImpl.java
    │           │                       └── Provider.java
    │           └── resources
    │               ├── META-INF
    │               │   └── spring
    │               │       └── dubbo-demo-provider.xml
    │               └── log4j.xml

    4. dubbo-demo-consumer - 服务消费者

    用下面的spring配置引用一个远程的dubbo服务(consumer.xml)
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
           http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
        <!-- 消费者应用名 -->
        <dubbo:application name="demo-consumer"/>
        <!-- 用zookeeper发现服务 -->
        <dubbo:registry address="zookeeper://${zookeeper_ip_addr}:2181"/>
        <!-- 生成远程服务的代理, 之后demoService就可以像使用本地接口一样使用了 -->
        <dubbo:reference id="demoService" check="false" interface="org.apache.dubbo.demo.DemoService"/>
    </beans>
    消费者启动类(Consumer.java)
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.apache.dubbo.demo.DemoService;
     
    public class Consumer {
        public static void main(String[] args) throws Exception {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"META-INF/spring/dubbo-demo-consumer.xml"});
            context.start();
            // Obtaining a remote service proxy
            DemoService demoService = (DemoService)context.getBean("demoService");
            // Executing remote methods
            String hello = demoService.sayHello("world");
            // Display the call result
            System.out.println(hello);
        }
    }
    配置好日志后(同provider),项目结构如下:
    ├── dubbo-demo-consumer
    │   ├── pom.xml
    │   └── src
    │       └── main
    │           ├── java
    │           │   └── org
    │           │       └── apache
    │           │           └── dubbo
    │           │               └── demo
    │           │                   └── consumer
    │           │                       └── Consumer.java
    │           └── resources
    │               ├── META-INF
    │               │   └── spring
    │               │       └── dubbo-demo-consumer.xml
    │               └── log4j.xml

    5. 完整示例

    • provider
    $ git clone https://github.com/apache/incubator-dubbo.git
    $ cd incubator-dubbo
    在模块dubbo-demo-provider下运行org.apache.dubbo.demo.provider.Provider
    如果用的IDE是Intellij Idea,需要添加参数:-Djava.net.preferIPv4Stack=true
    • consumer
    $ git clone https://github.com/apache/incubator-dubbo.git
    $ cd incubator-dubbo
    如果用的IDE是Intellij Idea,需要添加参数:-Djava.net.preferIPv4Stack=true

    传统dubbo服务迁移kubernetes

    •  打包

      mvn install #进入dubbo api目录安装dubbo api
      
      mvn package #打包
      
      tar -tf dubbo-demo-1.0-SNPASHOT-assembly.tar.gz 查看包中包含具体资源
    • 测试
      /bin/start.sh 启动服务
      
      查看接口是否开放 进程是否存在
      telnet ip dubbo端口连接
      
      ls 查看服务
      
      ls com.mooc.demo.api.DemoService 查看有哪些服务接口
      
      invoke com.mooc.demo.api.DemoService.sayHello("Dick")调用接口
      
      /bin/stop.sh 测试停止服务
    • 制作dockerfile并测试
      FROM hub.mooc.com/kubernetes/openjdk:8-jre-alpine
      
      COPY target/ROOT /ROOT
      
      ENTRYPOINT ["sh", "/ROOT/bin/start.sh"]
    • dubbo服务发现

    1.provider向zookeeper注册,zookeeper返回给consumer容器ip

    2.如整体架构都在k8s中则无问题,如consumer在集群之外。

    3.provider可将真实宿主机ip通过文件挂载方式configmap挂载到provider evn中。注册时使用真实ip。缺点(性能消耗不好,使用不方便)

    4.provider可使用宿主机网络,hostnetwork。直接与宿主机共用网络。缺点端口会增多混乱所以要规划好端口使用问题。

    5.优雅退出dubbo优雅退出是系统向程序发送一个SIGTERM信号kill 15终止信号,出发代码run中方法去执行下线流程。kubelet关闭容器默认也是发送SIGTERM kill 15信号与微服务契合。有可能遇到Pod卡死,处理不了优雅退出的命令或者操作、优雅退出的逻辑有BUG,陷入死循环、代码问题,导致执行的命令没有效果。所以可以在prostop中加入脚本向注册中心通知下线操作。

    • k8s部署文件
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: dubb-demo
      spec:
        selector:
          matchLabels:
            app: dubb-demo
        replicas: 1
        template:
          metadata:
            labels:
              app: dubb-demo
          spec:
            hostNetwork: true
            affinity:
              podAntiAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchExpressions:
                    - key: app
                      operator: In
                      values:
                      - dubb-demo
                  topologyKey: "kubernetes.io/hostname"
            containers:
            - name: dubb-demo
              image: hub.mooc.com/kubernetes/dubbo:v1
              ports:
              - containerPort: 20881
              env:
              - name: DUBBO_PORT
                value: "20881" #在启动文件中替换端口
      dubbo.yaml

    传统web服务迁移kubernetes

    • 打包测试
      mvn package
    • 构建dockerfile 
      FROM 172.17.166.217/kubenetes/tomcat:8.0.51-alpine
      
      COPY ROOT /usr/local/tomcat/webapps/ROOT
      
      COPY dockerfiles/start.sh /usr/local/tomcat/bin/start.sh
      
      ENTRYPOINT ["sh" , "/usr/local/tomcat/bin/start.sh"]
      tomcat.yaml
    • 镜像测试后将镜像上传库并制作k8s文件
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: web-demo
      spec:
        selector:
          matchLabels:
            app: web-demo
        replicas: 4
        template:
          metadata:
            labels:
              app: web-demo
          spec:
            containers:
            - name: web-demo
              image: hub.mooc.com/kubernetes/web:v1
              ports:
              - containerPort: 8080
      tomcat.yaml

      ###注默认tomcat启动是后台运行,容器收不到存活进程会自动退出,要在启动文件中编辑一个循环指令。类似于

      #!/bin/bash
      
      sh /usr/local/tomcat/bin/startup.sh
      
      tail -f /usr/local/tomcat/logs/catalina.out
  • 相关阅读:
    LeetCode1049. 最后一块石头的重量 II
    LeetCode416. 分割等和子集
    LeetCode96. 不同的二叉搜索树
    LeetCode343. 整数拆分
    python笔记---内置容器
    Numpy学习笔记(一)
    tensorflow入门代码分析
    神经网络
    回归算法
    机器学习入门笔记
  • 原文地址:https://www.cnblogs.com/dahuige/p/15019918.html
Copyright © 2011-2022 走看看