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
  • 相关阅读:
    PHP实现无限极分类
    html2canvas生成并下载图片
    一次线上问题引发的过程回顾和思考,以更换两台服务器结束
    Intellij IDEA启动项目报Command line is too long. Shorten command line for XXXApplication or also for
    mq 消费消息 与发送消息传参问题
    idea 创建不了 java 文件
    Java switch 中如何使用枚举?
    Collections排序
    在idea 设置 git 的用户名
    mongodb添加字段和创建自增主键
  • 原文地址:https://www.cnblogs.com/dahuige/p/15019918.html
Copyright © 2011-2022 走看看