2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)

springcloud微服务技术栈


文章目录

      • springcloud微服务技术栈
        • 1、基本概念
        • 2、微服务治理
          • 2.1、认识微服务
          • 2.2、服务拆分与远程调用
          • 2.3、eureka注册中心
          • 2.4、eureka+Ribbon负载均衡
          • 2.5、Nacos注册中心/数据中心
          • 2.6、Nacos与Eureka对比总结
          • 2.7、Nacos配置管理
          • 2.8、Nacos集群搭建
          • 2.9、Feign
          • 3.0、Gateway网关
          • 3.1、Gateway跨域问题访问
        • 3、Docker
          • 1、Docker的安装与使用
          • 2、DockerCompose
          • 3、nginx+nacos集群DockerCompose部署(读者要注意版本问题)
          • 解决指定端口问题(nacos2.x手动启动命令与拷贝命令的使用)
          • 4、docker镜像仓库
          • 声明:本文部分图片和代码源于个人学习中所寻资料,如有侵权联系,火速删文道歉。

1、基本概念

  • 微服务:分布式架构(把服务做拆分,拆分中产生的问题需要解决,springcloud仅仅解决了服务拆分的治理问题,然后再部署在不同的的机器上去)的一种。根据业务功能,将单体架构的项目拆分一个一个的独立项目(即服务)。

  • 技术栈

    • 微服务治理

    • 异步通信技术

    • 缓存技术

    • 搜索技术

    • 持续集成

2、微服务治理
2.1、认识微服务

  • 单体架构:将业务所有功能集成在一个项目中。缺点:耦合度高。优点:易于部署。
  • 分布式架构:缺点:部署难,拆分难,远程调用,地址维护,服务健康。优点:降低服务耦合。便于拓展。
  • 微服务:是一种经过良好架构设计的分布式架构方案。特征:单一职责(避免重复开发);面向服务(对外暴露业务接口);自治:独立开发互不影响;隔离性强:容错、降级处理。
  • 服务集群需要注册中心(拉取、注册服务信息)和配置中心(统一配置管理、实现热配置)。
  • 主流微服务技术栈对比
Dubbo SpringCloud SpringCloudAlibaba
注册中心 zookeeper、redis Eureka、Consul Nacos、Eureka
远程调用(接口约定、协议等) Dubbo协议 Feign(http协议,restful) Dubbo、Fegin
配置中心 SpringCloudConfig SpringCloudConfig、Nacos
服务网关 SpringCloudGateway、Zuul SpringCloudGateway、Zuul
服务监控和保护 dubbo-admin Hystrix Sentinel

技术体系:SpringCloudAlibaba+Fegin 性价比高。


补充:REST实质:URL中只使用名词来定位资源,用HTTP协议里的动词(GET、POST、PUT、DELETE)来实现资源的增删改查操作。

RESTful 风格:
RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用 XML 格式定义或 JSON 格式定义。最常用的数据格式是JSON。由于JSON能直接被JavaScript读取,所以,使用JSON格式的REST风格的API具有简单、易读、易用的特点。

(14条消息) RESTful 风格(详细介绍 + 案例实现)_Yan Yang的博客-CSDN博客_restful风格

  • Spring Cloud:集成了一整套微服务所需的组件,并基于SpringBoot做了自动装配。

2.2、服务拆分与远程调用

  • 服务拆分:1、不同微服务,不要重复开发相同非业务;2、微服务数据独立,不要访问其他服务数据库;3、微服务可以将自己的业务接口暴露。

  • 远程调用:本质是如何利用java发出对应的http请求。

    步骤

    • 1)在配置类中注册RestTemplate
    • 2)在需要发送http请求的类中自动装配使用即可
  • 提供者与消费者

    • 提供者:提供被调用的接口的服务;消费者:调用其他服务接口的服务

    • 一个服务既可以是提供者也可以是消费者


2.3、eureka注册中心

​ 1、作用

  • 1)解决消费者如何获取提供者信息。

  • 2)解决多个提供者,消费则如何选择。

  • 3)解决消费者如何感知提供者状态。

​ 2、基本概念和原理

​ eureka角色分为服务端和客户端

  • eureka-server
    • 注册服务:eureka-cli每30s发送心跳信息保证服务的状态,没心跳则去除该服务注册信息
    • 拉取服务:eureka-cli通过eureka-server进行远程调用
      • 负载均衡
  • eureka-cli
    • 提供者:注册信息到server;30s发一次心跳信息。
    • 消费者:根据服务名称从server中拉取服务;基于服务列表做负载均衡。

​ 3、eureka使用三步走 (eureka-server和eureka-client同理)

  • 1)依赖

    • 父工程中配置springboot版本支持的springcloud版本

      <properties>
          <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
          <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
          <java.version>1.8java.version>
          <spring-cloud.version>Hoxton.SR10spring-cloud.version>
          <mysql.version>5.1.47mysql.version>
          <mybatis.version>2.1.1mybatis.version>
      properties>
      
      • 开发的子工程中引入依赖
      <dependency>
          <groupId>org.springframework.cloudgroupId>
          <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
      dependency>
      
    • 2)注解启动:标注在主配置类下

    @EnableEurekaServer
    
    • 3)配置yml:提供服务名称;注册服务到服务中心;
    server:
      port: 10086 #服务端口
    spring:
      application:
        name: euraka-server #服务名称
    
    eureka:
      client:
        service-url:
          defaultZone: http://127.0.0.1:10086/eureka #注册地址 eureka-server本身也是一个服务因此需要进行注册(自己注册自己),后面集群时需要多个服务端进行相互注册注册
    

​ 4、eureka-client 拉取服务远程调用和负载均衡

  • 1)在注册RestTemplate方法添加@LoadBalanced 负载均衡注解
  • 2)替换之前的http请求中的硬编码格式,使用eureka-client中使用的服务名称(spring.application.name值)

2.4、eureka+Ribbon负载均衡

  • 使用:在注册RestTemplate方法上添加@LoadBalanced 负载均衡注解即可。
  • 负载均衡的大体历程:消费者需要怎样去拉取服务,就在那里的Rest Template处使用@LoadBalanced 配置负载均衡,restTemplate发起的请求会被LoadBalancerIntercepter类拦截。
    • 1、断点调试该类的intercept方法,该方法是的接口ClientHttpRequestInterceptor的方法实现;
    • 2、该方法中的:return (ClientHttpResponse)this.loadBalancer.execute(…));
    • 3、这个this.loadBalancer在运行中是LoadBalancerClient实现类的对象,正常情况下默认是RibbonLoadBalancerClient类的对象;
    • 4、进入该对象下的execute方法,发现得到了一个ILoadBalancer类的对象loadBalancer,而该对象中就已经获取到了eureka中的服务列表(每30s消费者会重新拉取获得该列表);
    • 5、下一句Server server = this.getServer(loadBalancer, hint)后续的执行链路就是在配置负载均衡。

2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第1张图片

  • 具体执行链路:

2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第2张图片

2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第3张图片

2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第4张图片

  • 修改负载均衡策略

    第一种方法:全局配置,在当前服务下,不管当前服务远程调用哪一个服务均采用此策略。

    • 1)注册一个IRule bean
    • 2)在该Bean下选择负载均衡策略(例如:RandomRule等)

    第二种方法:可以选择对哪一个远程调用的服务采用此策略。

    • 配置文件中修改

      eureka-client-user: #远程调用的服务名称
        ribbon: #负载均衡器
          NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #设置负载均衡策略
      
  • 饥饿加载

    • 基于上述的负载均衡执行流程,Ribbon在默认配置下采用懒加载,在第一次访问时才去创建LoadBalancerClient对象,请求时间长。

    • 饥饿加载会在项目启动时创建。

      配置:

      ribbon:
        eager-load:
          clients: #指定饥饿加载服务名称
            - eureka-client-user
          enabled: true #开启饥饿加载
      

2.5、Nacos注册中心/数据中心

  • 基本介绍:nacos是阿里巴巴的产品现在是springcloud中的一个组件,eureka2.x版本不再维护(没诞生),使用的1.x版本依旧在更新。

  • 对于eureka来说nacos的服务端是独立于项目启动,只需要在客户端配置服务端的主机地址和端口即可。又因为nacos遵循springcloud的通用接口所以在代码层面上不需要做改动,只需要修改配置文件即可。

  • 使用三步走

    • 1)启动nacos

      • 在nacos bin目录下使用:windows: startup.cmd -m standalone命令;liunx:sh startup.sh -m standalone命令
    • 2)添加依赖

      • 父工程中添加nacos整体版本信息

        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-alibaba-dependenciesartifactId>
            <version>2.2.5.RELEASEversion>
            <type>pomtype>
            <scope>importscope>
        dependency>
        
      • 子工程中引入nacos客户端依赖(如果项目中还使用了eureka依赖,则需要注释掉)

        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>
        
    • 3)配置配置文件(包括nacos服务地址+端口,如果存在eureka配置则需要注释掉)

      spring:
        cloud:
          nacos:
            discovery:
              server-addr: 127.0.0.1:8848 #nacos注册中心(server端)地址+端口
      

      注:如果在你的应用启动程序启动类加了@EnableEurekaClient ,需将其修改为@EnableDiscoveryClient ,或者索性删除。

  • 服务分级模型

    • nacos中把原来一个服务对应多实例的结构多加了一个集群做划分变成一个服务可以有多个集群,每个集群下对应多个实例。这样做的目的是因为:假设将一个服务在不同地方做部署的话,用户访问不同地方的服务实例可能会出现延迟高等问题,这时将不同地方的服务的多个实例作为集群进行划分,不同地区的用户只访问当前地区集群下的服务实例,只有该集群中所有的服务实例挂掉后才去访问其他地区的集群中的服务实例,这样就把延迟降低了。

    • 图示

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第5张图片

    • 服务分级模型的使用(降低不同地区远程调用服务延迟)

      • 1)先在不同地区部署,再将提供者的实例配置集群名称即可
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848 #nacos注册中心(server端)地址+端口
            cluster-name: CQ #CQ代表该集群实在重庆
      
      • nacos控制台展示

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第6张图片

      • 2)将不同地区部署的调用者设置集群(同上)

      • 3)调用者调整负载均衡策略,使用Nacos的负载均衡策略(如果不使用Nacos的负载均衡策略,采用轮询或者随机都不能使集群生效)

        userservice: #服务名
          ribbon:
            NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule #服务策略
        
      • 注:如果本地集群全挂掉,跨集群访问nacos会给出警告信息

  • 负载均衡:ribbon采用nacos负载均衡策略,有两种

    • 1)集群优先:上面提到的nacos策略默认是本地集群优先
    • 2)权重负载均衡:实际部署中根据不同集群的机器性能配置,通过nacos服务端对集群中的实例权重进行修改。权重为0,则不再使用该服务,此时可以实现将服务器进行平滑升级(慢慢调高权重)。
  • 环境隔离:不同于服务集群的不同,环境隔离是nacos提供的,其中服务和数据存储的最外层都有一个叫namespace的东西做隔离。

    • namespace(group(service/data)):隔离结构示意。

    图示

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第7张图片

    不同命名空间下的服务无法访问

    • 使用:

      • 1)新建命名空间

        2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第8张图片

      • 2)拷贝空间id

        在这里插入图片描述

      • 3)为服务配置命名空间

        spring:
          cloud:
            nacos:
              discovery:
                namespace: b979d985-6b2f-48b6-b04d-3d523818b300 #空间id
        

2.6、Nacos与Eureka对比总结

  • 服务提供者检测机制不同:nacos对每个服务实例默认为临时实例,nacos对于临时实例与eureka一样采用30s发送心跳消息的心跳检测机制;对于非临时服务实例,nacos注册中心会主动询问其健康状态。

  • 消费者服务列表更新方式不同:eureka让消费者每30s拉取一次服务列表;nacos除了采用该方式外,一旦注册中心发现有服务挂掉之后,立马通知消费者更新服务列表。

  • 配置临时实例与非临时实例

    spring:
      cloud:
        nacos:
          discovery:
            ephemeral: false #是否是临时实例,默认为true
    

2.7、Nacos配置管理

  • 统一配置管理:为了解决不同服务在升级或者需求变更情况下配置文件的修改问题,假如需要手动修改服务配置文件并生效,需要先关停服务、修改配置文件、重启服务,假如需要修改多个服务则此过程需要重复多次,整个流程下来耗时长且用户体验不好。因此统一配置管理可以把一些核心的配置、需要热更新(不用暂停服务)的配置进行统一管理,一旦配置完成重新发布,再由服务拉取配置即可。

  • 使用步骤

    • 1)在nacos服务端添加配置(Data ID命名规则:服务名+环境名.yaml),

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第9张图片

      并发布

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第10张图片

    • 2)服务拉取配置

      • 2.1)在服务拉取配置时,服务是先从nacos获取配置(例:上文中的eureka-client-user-dev.yaml)再合并本地的配置(一边来说是application.xml中的配置),所以需要再读取本地配置前想办法获取nacos中配置。解决办法是利用bootstrap.yml,该配置文件的读取优先级是高于application的,可以把服务的地址、端口以及nocas的注册中心的地址和端口等拉取所需信息配置到bootstrap.yml中。

        2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第11张图片

      • 2.2)引入依赖

        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
        dependency>
        
      • 2.3)配置bootstrap.yml(注意服务名称、环境要与Data Id一致,nacos注册中心地址+端口)

        spring:
          application:
            name: eureka-client-user #服务名称
          profiles:
            active: dev #环境
          cloud:
            nacos:
              discovery:
                server-addr: localhost:8848 #nacos服务端地址+端口
                ephemeral: false
                cluster-name: CQ
              config:
                file-extension: yaml #文件后缀名
                
        
    • 3)配置自更新:两种方式

      • 3.1)使用@Value读取配置文件中配置;在配置了@Value的类上添加@RefreshScope

        2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第12张图片

      • 3.2)创建一个配置类(不是spring中的@Configuration,实际上是一个bean),使用@ConfigurationProperties绑定配置属性的前缀,该类下的成员变量的名称要与配置文件中的属性一致,这样前缀拼接变量名即可。

        2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第13张图片

        2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第14张图片

    • 4)多环境共享配置:nacos Data Id配置命名:服务名.yml即可

      • 多环境下spring读取配置优先级:服务名+环境.yaml > 服务名.yaml >本地配置
    • 5)补充: 可以使用spring.cloud.nacos.config.enabled =false,来关闭Spring Cloud Nacos Config 配置功能。


2.8、Nacos集群搭建

  • 1)搭建MySQL集群并初始化数据库表
  • 2)下载nacos
  • 3)修改集群配置(节点信息)、数据库配置
  • 4)分别启动多个nacos
  • 5)nginx反向代理
    详细内容可以参考:nacos集群搭建
  • 踩坑记录
    • 物理内存小于启动时nacos的虚拟机内存设置

      • 解决办法:修改startup.cmd/sh 中 JAVA_OPT=“${JAVA_OPT} -Xms512m -Xmx512m -Xmn256m”。
    • 确保startup.sh/cmd启动脚本中JDK路径设置正确

      • 解决办法:确保nacos的启动所需JDK版本与安装的JDK版本一致且位数应与os位数一致,并保证启动脚本中的JDK路径设置正确。
    • MySql版本问题

      • 默认版本使用5,如果当前数据库版本是8.x需要在nacos目录下,新建plugins/mysql目录,放入版本8的连接包。
    • 本机nacos+nginx集群,服务注册不起问题

      • 解决办法:1)如果是系统是windows首先查看本机hosts文件,看看有没有开启127.0.0.1 localhost本机域名解析。如果没有开启那么cluster-conf与nginx中的配置均采用本机真实的ip地址,否则会出现服务注册失败的情况(微服务的服务发现配置无论是使用本机真实ip还是loclahost都不行)。如果你是采用127.0.0.1/localhost进行配置的话,所以要么修改配置文件中信息为真实ip,要么修改hosts文件开启本机域名解析。

      • 解决办法:2)查看nacos下的cluster-conf下是否多出了一个地址,然后查看该IP地址是不是你电脑的真实IP地址,如果不是,查看是不是你的虚拟网卡地址并禁用。

    • nacos注册服务的时候报错server is DOWN now, please try again later!

      • 此处报错是因为我复制的三分程序包之前使用过单机环境,不是新解压出来的;产生了data数据目录,里面的一些内容与当前的集群不兼容导致的;新解压出来的nacos是没有data目录的.
      • 解决办法:1.删除data下的protocol目录;2.重新解压一份新的程序(推荐)。
    • nacos服务从单机到集群转换时,本地服务注册失败

      • 在把单机环境下把已经部署过服务的naco服务端拷贝部署为集群之前一定要清理其data和logs目录的数据。

2.9、Feign

  • 本质是一个http客户端用来替代RestTemplate发出请求。

  • 解决RestTemplate:url复杂可读性差;请求参数难以维护。

  • feign集成了Rabbon

  • 使用步骤:

    • 1)导入依赖

      <dependency>
          <groupId>org.springframework.cloudgroupId>
          <artifactId>spring-cloud-starter-openfeignartifactId>
      dependency>
      
    • 2)消费者开启远程调用客户端使用

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第15张图片

    • 3)编写远程调用客户端声明

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第16张图片

    • 4)自动装配并使用

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第17张图片

  • feign的自定义配置
    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第18张图片

    • 日志配置:

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第19张图片

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第20张图片

  • Feign的优化

    • feign是一个声明式客户端,最终请求的发送还是装换成http请求,那么它的底层http客户端有三种。

      • 1)URL Connection
      • 2)Apache HttpClient
      • 3)OKhttp

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第21张图片

    • 优化:

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第22张图片

  • Feign的最佳实践

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第23张图片

    • 2)一般来说把这个依赖抽象成一个maven项目/启动器,之后项目导入即可。

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第24张图片

      • 解决该方案下client找不到包扫描问题

        • 1)

          2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第25张图片

        • 2)2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第26张图片


3.0、Gateway网关

  • 网关作用:1、用户身份认证、权限校验;2、将用户请求路由到微服务,并实现负载均衡;3、给用户请求做限流。

  • 问题:以前spring/springboot不是有安全框架做身份、权限验证吗?:现在是把业务流程按功能拆分成一个个的微服务,不能将所有的微服务都放开进行公共访问,所以安全验证统一交由网关去做去查看当前请求是否符合规范,网关身份相当于springmvc中的dispatchservlet对所有请求进行管理。

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第27张图片

  • 使用三步走:

    • 1)新建服务,引入依赖

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第28张图片

    • 2)编写路由配置

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第29张图片

    • 3)路由大体过程

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第30张图片

  • Gateway断言(predicates)配置详解

    • 断言工厂:predicates:我们指定其中属性是通过字符串,最终处理这些字符串的就是断言工厂(比如处理Path的PathRoutePredicateFactory)。用法与- Path一致。

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第31张图片

  • 路由过滤器

    • 过滤器大体执行流程

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第32张图片

    • Gateway过滤器工厂

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第33张图片

    • 使用方法:

      • 1)当前服务配置

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第34张图片

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第35张图片

      • 2)全局配置

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第36张图片

  • 全局路由过滤器

    • 简介:

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第37张图片

    • 定义一个全局过滤器

      //@Order(-1) //设置当前过滤器执行优先级,值越小优先级越高
      @Component  //组件注册
      public class AuthorizeFilter implements GlobalFilter, Ordered {
          @Override
          public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
              //1 获取请求参数
              ServerHttpRequest request = exchange.getRequest();
              MultiValueMap<String, String> queryParams = request.getQueryParams();
              //2.判断参数
              String authorized = queryParams.getFirst("authorized");
              //3
              if(authorized != null && authorized.equals("admin"))
                  return chain.filter(exchange);//放行
              else {//拦截
                  ServerHttpResponse response = exchange.getResponse();
                  response.setStatusCode(HttpStatus.UNAUTHORIZED);//设置响应头
                  return response.setComplete();
              }
          }
      
          @Override //同Order注解作用一样
          public int getOrder() {
              return -1;
          }
      }
      
  • 过滤器执行顺序:之前我们学过的过滤器最终会转化成Gatewayfilter再进行排序。

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第38张图片

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第39张图片


3.1、Gateway跨域问题访问

  • 跨域问题:出现在浏览器,微服务之间远程调用并没有问题。浏览器禁止请求发起者与服务端发生跨域ajax请求,被浏览器拦截。

  • 同源策略:域名+端口一致。

  • 解决办法:cors:浏览器先询问(询问即发出option请求,默认也是被拦截的)下服务端让不让这个请求跨域访问。

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第40张图片

    • maxAge:有效期,即加入每一次请求都要先询问发出option请求的话会非常耗时,所以设置maxAge在有效期内访问可以不用重复发option请求。

3、Docker
1、Docker的安装与使用

  • docker:虚拟化容器技术,docker基于镜像可以秒级启动各种容器。每一种容器都是一个完整的运行环境,容器(每一个容器即一个完整的运行环境)之间互相隔离。使用docker可以在镜像市场(docker hub)下载各种软件镜像。
    • 1)环境准备:virtualbox+linux(Vagrant官方镜像获取)vagrant(安装下载后)操作:vagrant init centos/7;(镜像名查看:Discover Vagrant Boxes - Vagrant Cloud (vagrantup.com))、修改Vagrantfile中的config.vm.network"private_network",ip:“IP地址值”,IP地址值,解决nat端口转换问题。
    • 2)centos中安装docker:Docker 容器使用 | 菜鸟教程 (runoob.com)
  • Dockerfile:用于自定义镜像。

2、DockerCompose

在这里插入图片描述

  • CentOS7安装DockerCompose

    Linux下需要通过命令下载:

    # 安装
    curl -L https://github.com/docker/compose/releases/download/1.23.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    

    如果下载速度较慢,或者下载失败,可以使用资料提供的docker-compose文件:

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第41张图片

    上传到宿主机/usr/local/bin/目录。

    修改文件权限:

    # 修改权限
    chmod +x /usr/local/bin/docker-compose
    

    2.3.Base自动补全命令:

    # 补全命令
    curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
    

    如果这里出现错误,需要修改自己的hosts文件:

    #1、
    echo "199.232.68.133 raw.githubusercontent.com" >> /etc/hosts
    #2、
    curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose -k #-k表示不进行证书检查,这样就可以直接下载了
    
  • 安装docker-compose:

    • 1)进入下载好的docker-compose目录(/usr/local/bin)
    • 2)sudo ln -s ./docker-compose /usr/bin/docker-compose
    • 3)测试:docker-compose --version
    • 补充:或者修改docker-compose文件执行权限后直接将该执行文件移入/usr/bin下。

3、nginx+nacos集群DockerCompose部署(读者要注意版本问题)

  • 虚拟机准备:virtualbox+vagrant下的centos7,最新版docker

  • 1)IP构建

    • 服务和nacos节点
nacos服务名 IP地址 端口
my-gateway 宿主机真实ip(192.168.56.10) 10086
order-service 192.168.56.10 8088
user-service 192.168.56.10 8089
nacos节点 IP地址 节点端口
nacos1 宿主机真实ip(192.168.56.10) 8845
nacos2 192.168.56.10 8846
nacos3 192.168.56.10 8847
nginx IP地址:localhost 监听端口:81
  • 2)准备基本容器

    • nacos2.0.2

      docker pull nacos/nacos-server:2.0.2
      
    • nginx最新版

      docker pull nginx
      
    • mysql8

      docker pull mysql:5.7.33
      
  • 3)创建挂载目录:
    在/home目录下创建三个目录,用于挂载 docker 容器的数据卷。

    mkdir -p /home/mysql
    
    mkdir -p /home/nacos
    
    mkdir -p /home/nacos-nginx
    
  • 4)mysal nacos数据初始化(数据库名:naocs 用户:root 密码:123456)这里省略了mysql容器创建过程,但是后面我补充了如何使用docker-compose的编排文件启动容器。

    CREATE TABLE `config_info` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `data_id` varchar(255) NOT NULL COMMENT 'data_id',
      `group_id` varchar(255) DEFAULT NULL,
      `content` longtext NOT NULL COMMENT 'content',
      `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
      `src_user` text COMMENT 'source user',
      `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
      `app_name` varchar(128) DEFAULT NULL,
      `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
      `c_desc` varchar(256) DEFAULT NULL,
      `c_use` varchar(64) DEFAULT NULL,
      `effect` varchar(64) DEFAULT NULL,
      `type` varchar(64) DEFAULT NULL,
      `c_schema` text,
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';
    
    /******************************************/
    /*   数据库全名 = nacos_config   */
    /*   表名称 = config_info_aggr   */
    /******************************************/
    CREATE TABLE `config_info_aggr` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `data_id` varchar(255) NOT NULL COMMENT 'data_id',
      `group_id` varchar(255) NOT NULL COMMENT 'group_id',
      `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
      `content` longtext NOT NULL COMMENT '内容',
      `gmt_modified` datetime NOT NULL COMMENT '修改时间',
      `app_name` varchar(128) DEFAULT NULL,
      `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租户字段';
    
    
    /******************************************/
    /*   数据库全名 = nacos_config   */
    /*   表名称 = config_info_beta   */
    /******************************************/
    CREATE TABLE `config_info_beta` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `data_id` varchar(255) NOT NULL COMMENT 'data_id',
      `group_id` varchar(128) NOT NULL COMMENT 'group_id',
      `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
      `content` longtext NOT NULL COMMENT 'content',
      `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
      `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
      `src_user` text COMMENT 'source user',
      `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
      `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';
    
    /******************************************/
    /*   数据库全名 = nacos_config   */
    /*   表名称 = config_info_tag   */
    /******************************************/
    CREATE TABLE `config_info_tag` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `data_id` varchar(255) NOT NULL COMMENT 'data_id',
      `group_id` varchar(128) NOT NULL COMMENT 'group_id',
      `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
      `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
      `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
      `content` longtext NOT NULL COMMENT 'content',
      `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
      `src_user` text COMMENT 'source user',
      `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';
    
    /******************************************/
    /*   数据库全名 = nacos_config   */
    /*   表名称 = config_tags_relation   */
    /******************************************/
    CREATE TABLE `config_tags_relation` (
      `id` bigint(20) NOT NULL COMMENT 'id',
      `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
      `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
      `data_id` varchar(255) NOT NULL COMMENT 'data_id',
      `group_id` varchar(128) NOT NULL COMMENT 'group_id',
      `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
      `nid` bigint(20) NOT NULL AUTO_INCREMENT,
      PRIMARY KEY (`nid`),
      UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
      KEY `idx_tenant_id` (`tenant_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';
    
    /******************************************/
    /*   数据库全名 = nacos_config   */
    /*   表名称 = group_capacity   */
    /******************************************/
    CREATE TABLE `group_capacity` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
      `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字符表示整个集群',
      `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
      `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
      `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
      `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数,,0表示使用默认值',
      `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
      `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_group_id` (`group_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='集群、各Group容量信息表';
    
    /******************************************/
    /*   数据库全名 = nacos_config   */
    /*   表名称 = his_config_info   */
    /******************************************/
    CREATE TABLE `his_config_info` (
      `id` bigint(64) unsigned NOT NULL,
      `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      `data_id` varchar(255) NOT NULL,
      `group_id` varchar(128) NOT NULL,
      `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
      `content` longtext NOT NULL,
      `md5` varchar(32) DEFAULT NULL,
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
      `src_user` text,
      `src_ip` varchar(50) DEFAULT NULL,
      `op_type` char(10) DEFAULT NULL,
      `tenant_id` varchar(128) DEFAULT '' COMMENT '租户字段',
      PRIMARY KEY (`nid`),
      KEY `idx_gmt_create` (`gmt_create`),
      KEY `idx_gmt_modified` (`gmt_modified`),
      KEY `idx_did` (`data_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租户改造';
    
    
    /******************************************/
    /*   数据库全名 = nacos_config   */
    /*   表名称 = tenant_capacity   */
    /******************************************/
    CREATE TABLE `tenant_capacity` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
      `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
      `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配额,0表示使用默认值',
      `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
      `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个配置大小上限,单位为字节,0表示使用默认值',
      `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大个数',
      `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '单个聚合数据的子配置大小上限,单位为字节,0表示使用默认值',
      `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大变更历史数量',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_tenant_id` (`tenant_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租户容量信息表';
    
    
    CREATE TABLE `tenant_info` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `kp` varchar(128) NOT NULL COMMENT 'kp',
      `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
      `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
      `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
      `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
      `gmt_create` bigint(20) NOT NULL COMMENT '创建时间',
      `gmt_modified` bigint(20) NOT NULL COMMENT '修改时间',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
      KEY `idx_tenant_id` (`tenant_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';
    
    CREATE TABLE `users` (
    	`username` varchar(50) NOT NULL PRIMARY KEY,
    	`password` varchar(500) NOT NULL,
    	`enabled` boolean NOT NULL
    );
    
    CREATE TABLE `roles` (
    	`username` varchar(50) NOT NULL,
    	`role` varchar(50) NOT NULL,
    	UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
    );
    
    CREATE TABLE `permissions` (
        `role` varchar(50) NOT NULL,
        `resource` varchar(255) NOT NULL,
        `action` varchar(8) NOT NULL,
        UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
    );
    
    INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);
    
    INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
    
  • 5)使用nacos编排文件(可选也可参照网络手动启动)注意:#后的内容是注释。

    version: "3"
    
    services: 
        nacos1:
            container_name: nacos-server01
            hostname: nacos-server01
            image: nacos/nacos-server:2.0.2
            environment: 
                - MODE=cluster
                - PREFER_HOST_MODE=hostname
                - NACOS_SERVERS=nacos-server01:8848 nacos-server02:8848
                - SPRING_DATASOURCE_PLATFORM=mysql
                - MYSQL_SERVICE_HOST=192.168.56.10
                - MYSQL_SERVICE_PORT=3306
                - MYSQL_SERVICE_USER=root
                - MYSQL_SERVICE_PASSWORD=123456
                - MYSQL_SERVICE_DB_NAME=nacos
                - JVM_XMS=128m
                - JVM_XMX=128m
                - JVM_XMN=128m
            volumes: 
                - /home/nacos2/cluster-logs/nacos-server01:/home/nacos/logs
                - /home/nacos2/init.d:/home/nacos/init.d
            ports: 
                - 8845:8848 #使用docker根据镜像创建,没办法更改默认application.properties
                # nacos会默认在当前naocs的端口上偏移1000和1001开启两个新端口,所以不能给nacos服务端配两个连续的端口。
                - 9848:9848 #9845 客户端gRPC请求服务端端口,用于客户端向服务端发起连接和请求,
                - 9849:9849 #9846 服务端gRPC请求服务端端口,用于服务间同步等
            restart: on-failure
    
    #为什么nacos1和2都是相同的端口?
    #可能原因:1)在容器启动时,容器内的文件会被容器外的文件覆盖掉,从而配置失效。
    #解决办法,使用命令手动启动一个单机版,拷贝单机的application,properties并修改其中的端口号为你像设定的端口(假设为8846),最后使用命令启动nacos容器再命令中把拷贝文件的目录进行挂载,同时还要指定端口为8846这样才能按照指定端口启动。
        nacos2:
            container_name: nacos-server02
            hostname: nacos-server02
            image: nacos/nacos-server:2.0.2
            environment: 
                - MODE=cluster
                - PREFER_HOST_MODE=hostname
                - NACOS_SERVERS=nacos-server01:8848 nacos-server02:8848
                - SPRING_DATASOURCE_PLATFORM=mysql
                - MYSQL_SERVICE_HOST=192.168.56.10
                - MYSQL_SERVICE_PORT=3306
                - MYSQL_SERVICE_USER=root
                - MYSQL_SERVICE_PASSWORD=123456
                - MYSQL_SERVICE_DB_NAME=nacos
                - JVM_XMS=128m
                - JVM_XMX=128m
                - JVM_XMN=128m
            volumes: 
                - /home/nacos/cluster-logs/nacos-server02:/home/nacos/logs
                - /home/nacos/init.d:/home/nacos/init.d
            ports: 
                - 8847:8848
            restart: on-failure
    
  • 6)查看日志启动成功:

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第42张图片

  • 6)Nginx 的部署

    • Nginx 的部署与其他服务部署略有不同,我们需要先启动一个 Nginx 容器实例,然后从容器事例中拷贝出 Nginx 的配置文件到指定目录,之后我们将复制出的配置文件与 Nginx 容器的数据卷进行挂载,从而达到可以在容器外部修改配置文件的目的。这么做是因为,如果直接挂载,那么容器实例中的的目录将会被外部的挂载所覆盖(nacos同理)。这是官方 Nginx 镜像的一个小缺陷,注意一下就行了。

    • 运行 Nginx 容器
      $ docker run --name temp-nginx -p 8080:8080 -d nginx:1.21.1
      
      在宿主机创建 Nginx 的挂载目录
      # 实际创建时以自己的机器环境为准
      
      $ mkdir -p <宿主机挂载目录>
      
      拷贝容器中的配置到宿主机的挂载目录
      $ docker cp :/etc/nginx/ <宿主机挂载目录>
      #例如:docker cp :/etc/nginx/ /home/docker/nginx/
      
      停止并删除容器实例
      $ docker stop 
      
      $ docker rm 
      
    • 修改 Nginx 配置文件

      位置:<宿主机挂载目录>/conf.d/default.conf
      
      配置文件主要修改两个部分,一个是新增 upstream,通过负载均衡来配置 Nacos 服务的节点;第二个是修改 server 下的 location,在其中添加反向代理配置。另外,如果你的 Nginx 没有配置过 server_name,那么还需要修改 server 下的 server_name 配置。
      下面给出两种配置:
      -----------------------------------1、----------------------------------------
      # 添加负载均衡配置
      #因为上面nacos配置的都是8848端口所以这里也都使用8848
      upstream nacos-cluster {
          server nacos-server01:8848 weight=1 max_fails=2 fail_timeout=10s;
          server nacos-server01:8848 weight=1 max_fails=2 fail_timeout=10s;
      }
      
      server {
      	#80端口可能会被其他应用占用保险起见还是改为81,当如如果80没用被占用仍可使用。
          listen       81; 
          #listen  [::]:80;
          # 修改为宿主机的 IP地址
          server_name  172.16.1.180;
      
          #access_log  /var/log/nginx/host.access.log  main;
      
          location / {
                  # 添加代理配置
              proxy_pass http://nacos;
              proxy_set_header Host $host;
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_set_header REMOTE-HOST $remote_addr;
              add_header X-Cache $upstream_cache_status;
              add_header Cache-Control no-cache;
      
              #root   /usr/share/nginx/html;
              #index  index.html index.htm;
          }
      
          #error_page  404              /404.html;
      
          # redirect server error pages to the static page /50x.html
          #
          error_page   500 502 503 504  /50x.html;
          location = /50x.html {
              root   /usr/share/nginx/html;
          }
      
          # proxy the PHP scripts to Apache listening on 127.0.0.1:80
          #
          #location ~ \.php$ {
          #    proxy_pass   http://127.0.0.1;
          #}
      
          # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
          #
          #location ~ \.php$ {
          #    root           html;
          #    fastcgi_pass   127.0.0.1:9000;
          #    fastcgi_index  index.php;
          #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
          #    include        fastcgi_params;
          #}
      
          # deny access to .htaccess files, if Apache's document root
          # concurs with nginx's one
          #
          #location ~ /\.ht {
          #    deny  all;
          #}
      }
      
      -------------------------------------2、--------------------------------------
      #新增,为了演示,故不配置权重
      upstream cluster {
      	server nacos-server01:8848;
      	server nacos-server02:8848;
      }
      
      server {
          listen       81;
          server_name  192.168.56.10;
      	#新增,配置nginx的日志级别debug
      	#error_log /var/log/nginx/debug.log debug;
          #新增,转向集群配置
      	location /nacos {
              proxy_pass http://cluster;
          }
      
          location / {
              root   /usr/share/nginx/html;
              index  index.html index.htm;
          }
      
          error_page   500 502 503 504  /50x.html;
          location = /50x.html {
              root   /usr/share/nginx/html;
          }
      
      }
      
      
    • Nginx编排文件

      version: "3"
      
      services: 
          nacos-nginx: 
              container_name: nacos-nginx
              image: nginx:1.21.1
              volumes: 
                  - /home/docker/nginx/nginx:/etc/nginx/
                  - /home/docker/nginx/www:/usr/share/nginx
              ports: 
                  - 8840:81
              restart: on-failure
      #重要说明:
      #数据卷挂载 - 本例中分别将 Nginx 的配置文件目录和静态文件资源目录挂载到了宿主机,如果不需要#提供静态资源访问,可以不用挂载此目录。
      #端口 - 本例中,为了避免与其他 Nginx 端口冲突,我们暴露的端口为 8840,其中 81 端口为容器#内部端口。
      
    • 打来浏览器输入:http://:8840/nacos,如果显示如下界面,则说明部署成功。

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第43张图片

  • 7)微服务部署

    • 修改application/bootsratp.yml中包含naccos服务发现配置(宿主机地址+nginx映射端口)

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第44张图片

    • 打包配置和Dockerfile文件

      <build>
              <finalName>appfinalName>
              <plugins>
                  <plugin>
                      <groupId>org.springframework.bootgroupId>
                      <artifactId>spring-boot-maven-pluginartifactId>
                  plugin>
              plugins>
          build>
      
    • 将打包好的jar包复制到宿主机的指定目录下,并编写Dockerfile

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第45张图片

      Dockerfile:

      FROM openjdk:8-alpine
      COPY ./app.jar /tmp/app.jar
      ENTRYPOINT java -jar /tmp/app.jar
      
    • 进入/tmp/dockertest/my-gateway/下,运行Dockerfile构建新镜像:

      docker build -t my-gateway:1.0 .
      
    • 运行镜像:

      docker run --name my-gateway01 up my-gateway:1.0
      
    • 启动成功:

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第46张图片
      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第47张图片
      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第48张图片


解决指定端口问题(nacos2.x手动启动命令与拷贝命令的使用)
  • 1)单机启动
docker run -it \
--net=host \
--name nacos-8846 \
-e NACOS_SERVER_PORT=8846 \
-e NACOS_SERVERS="nacos-8846:8846 nacos-8850:8850" \
-e MODE=cluster \
-e SPRING_DATASOURCE_PLATFORM=mysql \
-e MYSQL_SERVICE_HOST=192.168.56.10 \
-e MYSQL_SERVICE_PORT=3306 \
-e MYSQL_SERVICE_DB_NAME=nacos \
-e MYSQL_SERVICE_USER=root \
-e MYSQL_SERVICE_PASSWORD=123456 \
-e JVM_XMS=256m \
-e JVM_XMX=256m \
-e JVM_XMN=256m \
-p 8846:8846 \
nacos/nacos-server:2.0.2
-v /home/docker/nacos/conf:/home/nacos/conf \
-v /home/docker/nacos/logs:/home/nacos/logs \
-v /home/docker/nacos/data:/home/nacos/data \
  • 2)拷贝
docker cp  容器名:/home/nacos/conf 宿主机目录(比如/home/docker/nacos/conf)
  • 3)修改/home/docker/nacos/conf下的application.properties中的端口

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第49张图片

  • 4)挂载启动

    docker run -it \
    --net=host \
    --name nacos-8846 \
    -e NACOS_SERVER_PORT=8846 \
    -e NACOS_SERVERS="nacos-8846:8846 nacos-8850:8850" \
    -e MODE=cluster \
    -e SPRING_DATASOURCE_PLATFORM=mysql \
    -e MYSQL_SERVICE_HOST=192.168.56.10 \
    -e MYSQL_SERVICE_PORT=3306 \
    -e MYSQL_SERVICE_DB_NAME=nacos \
    -e MYSQL_SERVICE_USER=root \
    -e MYSQL_SERVICE_PASSWORD=123456 \
    -e JVM_XMS=256m \
    -e JVM_XMX=256m \
    -e JVM_XMN=256m \
    -p 8846:8846 \
    -v /home/docker/nacos/conf:/home/nacos/conf \
    -v /home/docker/nacos/logs:/home/nacos/logs \
    -v /home/docker/nacos/data:/home/nacos/data \
    nacos/nacos-server:2.0.2
    

    容器日志查看是否成功:docker logs -f nacos-8846

    2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第50张图片


  • mysql编排文件(可选)

    version: "3"
    
    services:
      mysql:
        container_name: mysql5
        image: mysql:5.7.33
        environment:
          - MYSQL_ROOT_PASSWORD=ok
        volumes:
          - /home/mysql/conf:/etc/mysql
          - /home/mysql/logs:/var/log/mysql
          - /home/mysql/data:/var/lib/mysql
        restart: on-failure
        ports:
          - 3306:3306
        privileged: true
        stdin_open: true
        tty: true
    
  • 使用编排部署 Nacos 集群(可选):

    docker-compose -f <编排文件路径> up -d
    
    • 踩坑1

      成功安装了docker-compose,但是一直提示command not found…:

      解决办法:

      //(1)sudo curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-( u n a m e − s ) − (uname -s)-(uname−s)−(uname -m) -o /usr/local/bin/docker-compose
      
      //(2)sudo chmod +x /usr/local/bin/docker-compose
      
      (3)sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
      
      (4) docker-compose --version
      
    • 踩坑2

      nacos-sever:v1.4.1和1.4.4运行不了:查看日志提示(Failed to bind properties under ‘server.tomcat.basedir’ to java.io.File)

      只能采用手动启动:

      docker run -d \
      --net=host \
      --restart=unless-stopped \
      --name nacos-server-1.4 \
      --env PREFER_HOST_MODE=hostname \
      --env MODE=cluster \
      --env NACOS_SERVERS=nacos-server01:8840,nacos-server02:8841 \
      --env NACOS_SERVER_IP=192.168.56.10 \
      --env SPRING_DATASOURCE_PLATFORM=mysql \
      --env MYSQL_SERVICE_HOST=192.168.56.10 \
      --env MYSQL_SERVICE_DB_NAME=nacos \
      --env MYSQL_SERVICE_USER=root \
      --env MYSQL_SERVICE_PASSWORD=123456 \
      -p 8840:8840 \
      nacos/nacos-server:1.4.1
      
    • 踩坑3

      nacos在运行时不能把其配置文件进行挂载否则会出错。


4、docker镜像仓库

2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第51张图片

  • 搭建私有仓库镜像

    • 1)简单搭建

      Docker官方的Docker Registry是一个基础版本的Docker镜像仓库,具备仓库管理的完整功能,但是没有图形化界面。

      搭建方式比较简单,命令如下:

      docker run -d \
          --restart=always \
          --name registry	\
          -p 5000:5000 \
          -v registry-data:/var/lib/registry \
          registry
      

      命令中挂载了一个数据卷registry-data到容器内的/var/lib/registry 目录,这是私有镜像库存放数据的目录。

      访问http://YourIp:5000/v2/_catalog 可以查看当前私有镜像服务中包含的镜像

    • 2)带有图形化界面版本

      使用DockerCompose部署带有图象界面的DockerRegistry,命令如下:

      version: '3.0'
      services:
        registry:
          image: registry
          volumes:
            - ./registry-data:/var/lib/registry
        ui:
          image: joxit/docker-registry-ui:static
          ports:
            - 8180:80
          environment:
            - REGISTRY_TITLE=我的私有仓库
            - REGISTRY_URL=http://registry:5000
          depends_on:
            - registry
      

      配置Docker信任地址

      我们的私服采用的是http协议,默认不被Docker信任,所以需要做一个配置:

      # 打开要修改的文件
      vi /etc/docker/daemon.json
      # 添加内容:
      "insecure-registries":["http://192.168.56.10:8180"]
      # 重加载
      systemctl daemon-reload
      # 重启docker
      systemctl restart docker
      

      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第52张图片
      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第53张图片
      2023-3-1 微服务技术栈(基本概念+微服务治理+docker+踩坑记录)_第54张图片


声明:本文部分图片和代码源于个人学习中所寻资料,如有侵权联系,火速删文道歉。

你可能感兴趣的:(微服务,docker,java)