• Spring Cloud:多环境配置、eureka 安全认证、容器宿主机IP注册


    记录一下搭建 Spring Cloud 过程中踩过的一些坑,测试的东西断断续续已经弄了好多了,一直没有时间整理搭建过程,时间啊~时间~

    Spring 版本

    • Spring Boot:2.0.6.RELEASE
    • Spring Cloud:Finchley.SR2

    多环境配置切换

    使用 Spring Cloud 来处理

    多配置的切换在开发中真是很常用,能有效提高效率。一些成熟的框架基本都有关于配置切换的解决方案,当然了 Spring Cloud 也不例外!

    先看看我的配置文件结构:

    配置文件通过后缀区分:dev - 开发环境配置,test - 测试环境配置,prod - 生产环境配置。

    bootstrap.yml 文件来配置加载那个配置文件:

    spring:
      profiles:
        active: dev

     spring.profiles.active 配置的就是需要加载的配置文件,这样就能通过配置来加载不同的配置文件。

    这里说明一下配置的加载流程:bootstrap.yml ----> bootstrap-{profile}.yml ----> application.yml ----> application-{profile}.yml

    也就是说,无论 bootstrap 还是 appliction 都可以做多环境配置切换的。 

    但是,我们一般都是打包成 jar 包来运行,这样分别打包还是有点麻烦,所以可以打包一个 jar 包,通过添加启动参数来加载不同的配置:

    java -jar xxx.jar --spring.profiles.active=dev 表示使用开发环境的配置
    java -jar xxx.jar --spring.profiles.active=test 表示使用测试环境的配置
    java -jar xxx.jar --spring.profiles.active=prod 表示使用生产环境的配置

    这里贴一个我封装的启动 jar 包的 shell 脚本:

    #!/bin/bash
    JAR_DIR='/data'
    JAR_FILE=''
    LOG_DIR='/dev/null'
    CONF_ENV='dev'
    JAR_NUM=1
    
    if read -t 30 -p "Enter the jar storage directory(default: $JAR_DIR): " I_JAR_DIR
    then
    
        if [ "$I_JAR_DIR" != "" ]
        then
            if [ ! -d "$I_JAR_DIR" ];then
                echo "Error: Directory does not exist;"
                exit 1
            fi
            JAR_DIR=$I_JAR_DIR
        fi
    
    else
        echo
        echo "Error: Sorry, too slow"
        exit 1
    fi
    
    JAR_FILE_LIST=$(ls -1 $JAR_DIR | awk '/.*.jar$/')
    if [ "$JAR_FILE_LIST" = "" ]
    then
        echo "Error: There is no runnable jar package"
        exit 1
    else
        echo "--------------------------------------------------"
        echo "$JAR_FILE_LIST" | awk '/.*.jar$/{print NR,$0}'
        echo "--------------------------------------------------"
    
        if read -t 30 -p "Enter the line number to run the jar package(default: $JAR_NUM): " I_JAR_NUM
        then
            if [ "$I_JAR_NUM" = "" ];then
                I_JAR_NUM=$JAR_NUM
            fi
            if [ ! -n "$(echo $I_JAR_NUM| sed -n "/^[0-9]+$/p")" ] || [ $I_JAR_NUM -lt 1 ]
            then
                echo "Error: Illegal jar package line number"
                exit 1
            else
                JARSTR=$(echo "$JAR_FILE_LIST" | awk '{print $0 "|||"}')
                OLD_IFS="$IFS"
                IFS="|||"
                JAR_TEM=($JARSTR)
                IFS="$OLD_IFS"
                JAR_ARRAY=()
                JAR_ARRAY_i=1
                for var in ${JAR_TEM[@]}
                do
                    if [ "$var" != "" ]
                    then
                        JAR_ARRAY[$JAR_ARRAY_i]=$var
                        JAR_ARRAY_i=$(($JAR_ARRAY_i+1))
                    fi
                done
                JAR_NUM=$I_JAR_NUM
            fi
    
        else
            echo
            echo "Error: Sorry, too slow"
            exit 1
        fi
    fi
    
    if read -t 30 -p "Enter the log storage directory(default: $LOG_DIR): " I_LOG_DIR
    then
    
        if [ "$I_LOG_DIR" != "" ]
        then
            if [ ! -d "$I_LOG_DIR" ];then
                echo "Error: Directory does not exist;"
                exit 1
            fi
            LOG_DIR=$I_LOG_DIR
        fi
    
    else
        echo
        echo "Error: Sorry, too slow"
        exit 1
    fi
    
    if read -t 30 -p "Input configuration environment(default: $CONF_ENV): " I_CONF_ENV
    then
    
        if [ "$I_CONF_ENV" != "" ]
        then
            CONF_ENV=$I_CONF_ENV
        fi
    
    else
        echo
        echo "Error: Sorry, too slow"
        exit 1
    fi
    
    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    
    if [ "$LOG_DIR" != "/dev/null" ]
    then
        LOG_URI=${LOG_DIR%*/}/${JAR_ARRAY[$JAR_NUM]}_"$CONF_ENV"_$(date "+%Y_%b_%d_%H_%M_%S_%N").txt
    else
        LOG_URI=$LOG_DIR
    fi
    exec java -jar ${JAR_DIR%*/}/${JAR_ARRAY[$JAR_NUM]} > $LOG_URI --spring.profiles.active=$CONF_ENV &
    echo "The successful running."

    使用环境变量来处理

    也有很多人选择使用这种方式来处理,这主要是使用场景是使用 Docker 构建 Sprign 项目,通过运行容器时候初始化一些环境变量来指定配置。

    可以参考下面的文件了解一下:

    docker-compose.yml:

    # local development configuration
    
    version: '2.1'
    services:
      standalone.eureka-develop:
        extends:
          service: base-eureka
          file: docker-compose-base.yml
        container_name: ${CONTAINER_HOST_NAME:-standalone.eureka}
        environment:
        - CONTAINER_HOST_NAME=${CONTAINER_HOST_NAME:-standalone.eureka}
        - EUREKA_CLIENT_FETCHREGISTRY=false
        - EUREKA_CLIENT_REGISTERWITHEUREKA=false
        - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://${SPRING_SECURITY_USER_NAME:-user}:${SPRING_SECURITY_USER_PASSWORD:-user_pass}@standalone.eureka:${SERVER_PORT:-8761}/eureka/
        #- EUREKA_INSTANCE_HOSTNAME=${CONTAINER_HOST_NAME:-standalone.eureka}
        - EUREKA_INSTANCE_IPADDRESS=${HOST_IPADDRESS:-172.16.238.10}
    
    
        - EUREKA_INSTANCE_REGISTRY_DEFAULTOPENFORTRAFFICCOUNT=${EUREKA_INSTANCE_REGISTRY_DEFAULTOPENFORTRAFFICCOUNT:-1}
        - EUREKA_SERVER_ENABLESELFPRESERVATION=${EUREKA_SERVER_ENABLESELFPRESERVATION:-true}
        - EUREKA_SERVER_RENEWALPERCENTTHRESHOLD=${EUREKA_SERVER_RENEWALPERCENTTHRESHOLD:-0.25}
    
    
        - SPRING_APPLICATION_NAME=standalone.eureka
        - SPRING_CLOUD_CLIENT_HOSTNAME=${CONTAINER_HOST_NAME:-standalone.eureka}
        - SPRING_CLOUD_CLIENT_IPADDRESS=${HOST_IPADDRESS:-172.16.238.10}
        - SPRING_PROFILES_ACTIVE=develop.env,manual_ip_hostname,port_nonsecure,standalone
    
    
    
        hostname: ${CONTAINER_HOST_NAME:-standalone.eureka}
        networks:
          local-network:
            ipv4_address: 172.16.238.10
            #ipv6_address: 2001:3984:3989::10
        ports:
        - "${SERVER_PORT:-8761}:${SERVER_PORT:-8761}"
        volumes:
        - data:/home/alpine/data
        - tmp:/tmp
    
    networks:
      # docker network create --driver=bridge --ipam-driver=default --subnet=172.16.238.0/24 local-network
      # docker network ls
      # docker network inspect local-network
      local-network:
        external: true
        driver: bridge
        enable_ipv6: true
        ipam:
          driver: default
          config:
          - subnet: 172.16.238.0/24
          #- subnet: 2001:3984:3989::/64
    
    volumes:
      data:
        driver: local
        driver_opts:
          type: none
          device: ${PWD}/data/data
          o: bind
      tmp:
        driver: local
        driver_opts:
          type: none
          device: ${PWD}/data/tmp
          o: bind

    application.yml

    eureka.client:
    #  # Indicates whether server can redirect a client request to a backup server/cluster.
    #  # If set to false, the server will handle the request directly,
    #  # If set to true, it may send HTTP redirect to the client, with a new server location.
    #  # default: false
    #  allow-redirects: false
    #  # Gets the list of availability zones (used in AWS data centers) for the region in which this instance resides.
    #  # The changes are effective at runtime at the next registry fetch cycle as specified by registryFetchIntervalSeconds.
    #  # default: <blank-value>
    #  #availability-zones:
    #  # Gets the name of the implementation which implements BackupRegistry to fetch the registry information
    #  # as a fall back option for only the first time when the eureka client starts.
    #  # This may be needed for applications which needs additional resiliency for registry information without which it cannot operate.
    #  # default: <blank-value>
    #  #backup-registry-impl:
    #  # Cache refresh executor exponential back off related property.
    #  # It is a maximum multiplier value for retry delay, in case where a sequence of timeouts occurred.
    #  # default: 10
    #  cache-refresh-executor-exponential-back-off-bound: 10
    #  # The thread pool size for the cacheRefreshExecutor to initialise with
    #  # default: 2
    #  cache-refresh-executor-thread-pool-size: 2
    #  # EurekaAccept name for client data accept
    #  # default: <blank-value>
    #  #client-data-accept:
    #  # This is a transient config and once the latest codecs are stable, can be removed (as there will only be one)
    #  # default: <blank-value>
    #  #decoder-name:
    #  # Indicates whether the eureka client should disable fetching of delta and should rather resort to getting the full registry information.
    #  # Note that the delta fetches can reduce the traffic tremendously, because the rate of change with the eureka server is normally much lower than the rate of fetches.
    #  # The changes are effective at runtime at the next registry fetch cycle as specified by registryFetchIntervalSeconds
    #  # default: false
    #  disable-delta: false
    #  # Get a replacement string for Dollar sign <code>$</code> during serializing/deserializing information in eureka server.
    #  # default: _-
    #  #dollar-replacement: _-
    #  # Flag to indicate that the Eureka client is enabled.
    #  # default: true
    #  #   client是否可用, 通常测试时不需要启用真实服务时需要
    #  enabled: true
    #  # This is a transient config and once the latest codecs are stable, can be removed (as there will only be one)
    #  # default: <blank-value>
    #  #encoder-name:
    #  # Get a replacement string for underscore sign <code>_</code> during serializing/deserializing information in eureka server.
    #  # default: __
    #  #escape-char-replacement: __
    #  # Indicates how much time (in seconds) that the HTTP connections to eureka server can stay idle before it can be closed.
    #  # In the AWS environment, it is recommended that the values is 30 seconds or less,
    #  # since the firewall cleans up the connection information after a few mins leaving the connection hanging in limbo
    #  # default: 30
    #  #   单位s, 一个到Eureka的Http连接在关闭前可以保持Idle状态的最大时间
    #  eureka-connection-idle-timeout-seconds: 30
    #  # default eureka
    #  eureka-server-u-r-l-context: eureka
    #  # Indicates how long to wait (in seconds) before a connection to eureka server needs to timeout.
    #  # Note that the connections in the client are pooled by org.apache.http.client.HttpClient and
    #  # this setting affects the actual connection creation and also the wait time to get the connection from the pool.
    #  # default: 5
    #  eureka-server-connect-timeout-seconds: 5
    #  # Gets the DNS name to be queried to get the list of eureka servers.
    #  # This information is not required if the contract returns the service urls by implementing serviceUrls.
    #  # The DNS mechanism is used when useDnsForFetchingServiceUrls is set to true and
    #  # the eureka client expects the DNS to configured a certain way so that it can fetch changing eureka servers dynamically.
    #  # The changes are effective at runtime.
    #  # default: <blank-value>
    #  #eureka-server-d-n-s-name:
    #  # Gets the port to be used to construct the service url to contact eureka server when the list of eureka servers come from the DNS.
    #  # This information is not required if the contract returns the service urls eurekaServerServiceUrls(String).
    #  # The DNS mechanism is used when useDnsForFetchingServiceUrls is set to true and
    #  # the eureka client expects the DNS to configured a certain way so that it can fetch changing eureka servers dynamically.
    #  # The changes are effective at runtime.
    #  # default: <blank-value>
    #  #eureka-server-port:
    #  # Indicates how long to wait (in seconds) before a read from eureka server needs to timeout.
    #  # default: 8
    #  #   单位s, 读数据超时时长
    #  eureka-server-read-timeout-seconds: 8
    #  # Gets the total number of connections that is allowed from eureka client to all eureka servers.
    #  # default: 200
    #  #   Client到Eureka的最大连接数
    #  eureka-server-total-connections: 200
    #  # Gets the total number of connections that is allowed from eureka client to a eureka server host.
    #  # default: 50
    #  #   Client到单个Eureka的最大链接数
    #  eureka-server-total-connections-per-host: 50
    #  # Gets the URL context to be used to construct the service url to contact eureka server when the list of eureka servers come from the DNS.
    #  # This information is not required if the contract returns the service urls from eurekaServerServiceUrls.
    #  # The DNS mechanism is used when useDnsForFetchingServiceUrls is set to true and
    #  # the eureka client expects the DNS to configured a certain way so that it can fetch changing eureka servers dynamically.
    #  # The changes are effective at runtime.
    #  # default: <blank-value>
    #  #eureka-server-u-r-l-context:
    #  # Indicates how often(in seconds) to poll for changes to eureka server information.
    #  # Eureka servers could be added or removed and this setting controls how soon the eureka clients should know about it.
    #  # default: 0
    #  #   单位s, 客户端拉取Eureka的状态变化(Instances增删)的时间间隔
    #  eureka-service-url-poll-interval-seconds: 0
      # Indicates whether this client should fetch eureka registry information from eureka server.
      # default: true
      #   是否从Eureka获取集群Instances信息
      fetch-registry: ${EUREKA_CLIENT_FETCHREGISTRY:false}
    #  # Comma separated list of regions for which the eureka registry information will be fetched.
    #  # It is mandatory to define the availability zones for each of these regions as returned by availabilityZones.
    #  # Failing to do so, will result in failure of discovery client startup.
    #  # default: <blank-value>
    #  #fetch-remote-regions-registry:
    #  # Indicates whether to get the applications after filtering the applications for instances with only InstanceStatus UP states.
    #  # default: true
    #  #   是否只给出处于存活(UP)状态的应用
    #  filter-only-up-instances: true
    #  # Indicates whether the content fetched from eureka server has to be compressed whenever it is supported by the server.
    #  # The registry information from the eureka server is compressed for optimum network traffic.
    #  # default: true
    #  #   如果Eureka服务端支持, Client从Eureka获取gzip压缩过的数据
    #  g-zip-content: true
      # see: https://github.com/spring-cloud/spring-cloud-netflix/blob/v1.4.4.RELEASE/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaDiscoveryClientConfiguration.java
      healthcheck.enabled: ${EUREKA_CLIENT_HEALTHCHECK_ENABLED:true}
    #  # Heartbeat executor exponential back off related property.
    #  # It is a maximum multiplier value for retry delay, in case where a sequence of timeouts occurred.
    #  # default: 10
    #  heartbeat-executor-exponential-back-off-bound: 10
    #  # The thread pool size for the heartbeatExecutor to initialise with
    #  # default: 2
    #  #   向Eureka发送心跳的线程池大小
    #  heartbeat-executor-thread-pool-size: 2
    #  # Indicates how long initially (in seconds) to replicate instance info to the eureka server
    #  # default: 40
    #  #   单位s, 启动后, 间隔多少时间后开始复制instance info到Eureka
    #  initial-instance-info-replication-interval-seconds: 40
    #  # Indicates how often(in seconds) to replicate instance changes to be replicated to the eureka server.
    #  # default: 30
    #  #   单位s, 每间隔多少时间复制instance info变动到Eureka
    #  instance-info-replication-interval-seconds: 30
    #  # Indicates whether to log differences between the eureka server and the eureka client in terms of registry information.
    #  # Eureka client tries to retrieve only delta changes from eureka server to minimize network traffic.
    #  # After receiving the deltas, eureka client reconciles the information from the server to verify it has not missed out some information.
    #  # Reconciliation failures could happen when the client has had network issues communicating to server.
    #  # If the reconciliation fails, eureka client gets the full registry information.
    #  # While getting the full registry information, the eureka client can log the differences between the client and the server and this setting controls that.
    #  # The changes are effective at runtime at the next registry fetch cycle as specified by registryFetchIntervalSecondsr
    #  # default: false
    #  #   是否记录Eureka与Client之间关于注册信息的差异
    #  log-delta-diff: false
    #  # If set to true, local status updates via ApplicationInfoManager will trigger on-demand (but rate limited) register/updates to remote eureka servers
    #  # default: true
    #  #   通过ApplicationInfoManager修改的状态变化是否更新到Eureka
    #  on-demand-update-status-change: true
    #  # Indicates whether or not this instance should try to use the eureka server in the same zone for latency and/or other reason.
    #  # Ideally eureka clients are configured to talk to servers in the same zone
    #  # The changes are effective at runtime at the next registry fetch cycle as specified by registryFetchIntervalSeconds
    #  # default: true
    #  #   倾向使用于Client处在同一Zone内的Eureka
    #  prefer-same-zone-eureka: true
    #  # default: <blank-value>
    #  #property-resolver:
    #  # Gets the proxy host to eureka server if any.
    #  # default: <blank-value>
    #  #proxy-host:
    #  # Gets the proxy password if any.
    #  # default: <blank-value>
    #  #roxy-password:
    #  # Gets the proxy port to eureka server if any.
    #  # default: <blank-value>
    #  #proxy-port:
    #  # Gets the proxy user name if any.
    #  # default: <blank-value>
    #  #proxy-user-name:
      # Gets the region (used in AWS datacenters) where this instance resides.
      # default: us-east-1
      region: ${EUREKA_CLIENT_REGION:us-east-1}
      # Indicates whether or not this instance should register its information with eureka server for discovery by others.
      # In some cases, you do not want your instances to be discovered whereas you just want do discover other instances.
      # default: true
      #   是否将服务发布到Eureka
      register-with-eureka: ${EUREKA_CLIENT_REGISTERWITHEUREKA:false}
    #  # Indicates how often(in seconds) to fetch the registry information from the eureka server.
    #  # default: 30
    #  #   单位s, 间隔多长时间从Eureka获取注册信息
    #  registry-fetch-interval-seconds: 30
      # Indicates whether the client is only interested in the registry information for a single VIP.
      # default: <blank-value>
      #registry-refresh-single-vip-address:
      # Map of availability zone to list of fully qualified URLs to communicate with eureka server.
      # Each value can be a single URL or a comma separated list of alternative locations.
      # Typically the eureka server URLs carry protocol,host,port,context and version information if any.
      # Example: http://ec2-256-156-243-129.compute-1.amazonaws.com:7001/eureka/
      # The changes are effective at runtime at the next service url refresh cycle as specified by eurekaServiceUrlPollIntervalSeconds.
      # default: <blank-value>
      service-url:
        #   Note:
        #   Peer Awareness Mode: eureka.client.service-url.defaultZone's hosts affect DS Replicas value on dashboard
        #   Standalone Mode: Notice that the serviceUrl is pointing to the same host as the local instance.
        #   Note: must use 'defaultZone' here, otherwise cluster peers can not find replicas (can not see each other).
        #   split by comma
        defaultZone: ${EUREKA_CLIENT_SERVICEURL_DEFAULTZONE:http://${security.user.name:user}:${security.user.password:user_pass}@${EUREKA_INSTANCE_HOSTNAME:standalone.eureka}:${server.port}/eureka/}
    #  # default: <blank-value>
    #  #transport:
    #  # Indicates whether the eureka client should use the DNS mechanism to fetch a list of eureka servers to talk to.
    #  # When the DNS name is updated to have additional servers, that information is used immediately after
    #  # the eureka client polls for that information as specified in eurekaServiceUrlPollIntervalSeconds.
    #  # Alternatively, the service urls can be returned serviceUrls, but the users should implement their own mechanism to return the updated list in case of changes.
    #  # The changes are effective at runtime.
    #  # default: false
    #  #use-dns-for-fetching-service-urls:
    
    #eureka.dashboard:
    #  # Flag to enable the Eureka dashboard. Default true.
    #  # default: true
    #  #   whether enable dashboard
    #  enabled: true
    #  # The path to the Eureka dashboard (relative to the servlet path). Defaults to "/".
    #  # default: /
    #  #   path of dashboard
    #  path: /
    
    eureka.instance:
    #  # Gets the AWS autoscaling group name associated with this instance.
    #  # This information is specifically used in an AWS environment to automatically put an instance out of service after the instance is launched and it has been disabled for traffic..
    #  # default: <blank-value>
    #  #a-s-g-name:
    #  # Get the name of the application group to be registered with eureka.
    #  # default: <blank-value>
    #  #   application name on (register to) eureka
    #  #app-group-name:
      # Get the name of the application to be registered with eureka.
      # default: unknown
      #   application name on (register to) eureka, all instances of an application must use same value
      appname: ${SPRING_APPLICATION_NAME:standalone.eureka}
    #  # Returns the data center this instance is deployed. This information is used to get some AWS specific instance information if the instance is deployed in AWS.
    #  # default: <blank-value>
    #  #data-center-info:
    #  # default: []
    #  #default-address-resolution-order: []
    #  # default: <blank-value>
    #  #environment:
    #  # Gets the relative health check URL path for this instance.
    #  # The health check page URL is then constructed out of the hostname and the type of communication - secure or unsecure as specified in securePort and nonSecurePort.
    #  # It is normally used for making educated decisions based on the health of the instance - for example,
    #  # it can be used to determine whether to proceed deployments to an entire farm or stop the deployments without causing further damage.
    #  #   健康检查URL的ContextPath
    #  # default: /health
    #  health-check-url-path: /health
    #  # Gets the absolute home page URL for this instance.
    #  # The users can provide the homePageUrlPath if the home page resides in the same instance talking to eureka,
    #  # else in the cases where the instance is a proxy for some other server, users can provide the full URL.
    #  # If the full URL is provided it takes precedence.
    #  # It is normally used for informational purposes for other services to use it as a landing page.
    #  # The full URL should follow the format http://${eureka.hostname}:7001/ where the value ${eureka.hostname} is replaced at runtime.
    #  # default: <blank-value>
    #  #   instance's URL
    #  #home-page-url:
    #  # Gets the relative home page URL Path for this instance. The home page URL is then constructed out of the hostName and the type of communication - secure or unsecure.
    #  # It is normally used for informational purposes for other services to use it as a landing page.
    #  # default: /
    #  #   instance's context-path
    #  home-page-url-path: /
    #  # default: <blank-value>
    #  #host-info:
      # The hostname if it can be determined at configuration time (otherwise it will be guessed from OS primitives).
      # default: <blank-value>
      #   eureka.instance.hostname affect Status->instances's url href (not text) value on dashboard
      hostname: ${EUREKA_INSTANCE_HOSTNAME:${spring.cloud.client.hostname:standalone.eureka}}
    #  # default: <blank-value>
    #  #inet-utils:
    #  # Initial status to register with remote Eureka server.
    #  # default: <blank-value>
    #  #   注册到Eureka时的初始状态
    #  #initial-status:
    #  # Indicates whether the instance should be enabled for taking traffic as soon as it is registered with eureka.
    #  # Sometimes the application might need to do some pre-processing before it is ready to take traffic.
    #  # default: false
    #  #   实例注册后是否可以立刻提供服务, 通常注册后在提供服务前还需要做些预处理
    #  instance-enabled-onit: false
      # Get the IPAdress of the instance.
      # This information is for academic purposes only as
      # the communication from other instances primarily happen using the information supplied in {@link #getHostName(boolean)}.
      # default: <blank-value>
      #   如果未找到IP地址, 集群结点间无法互相注册
      ip-address: ${EUREKA_INSTANCE_IPADDRESS:${spring.cloud.client.ip-address:127.0.0.1}}
    #  # Indicates the time in seconds that the eureka server waits since it received the last heartbeat
    #  # before it can remove this instance from its view and there by disallowing traffic to this instance.
    #  # Setting this value too long could mean that the traffic could be routed to the instance
    #  # even though the instance is not alive.
    #  # Setting this value too small could mean, the instance may be taken out of traffic because of temporary network glitches.
    #  # This value to be set to atleast higher than the value specified in leaseRenewalIntervalInSeconds.
    #  # default: 90
    #  #   单位s, 实例可被Eureka移除的秒数, 从Eureka最后一次收到实例心跳消息计算
    #  lease-expiration-duration-in-seconds: 90
    #  # Indicates how often (in seconds) the eureka client needs to send heartbeats to eureka server to indicate that it is still alive.
    #  # If the heartbeats are not received for the period specified in leaseExpirationDurationInSeconds,
    #  # eureka server will remove the instance from its view, there by disallowing traffic to this instance.
    #  # Note that the instance could still not take traffic if it implements HealthCheckCallback and then decides to make itself unavailable.
    #  # default: 30
    #  #   单位s, Client发送心跳的时间间隔
    #  lease-renewal-interval-in-seconds: 30
    #  # Get the namespace used to find properties. Ignored in Spring Cloud.
    #  # default: eureka
    #  #   查找属性时使用的名称空间, spring-cloud中已忽略
    #  namespace: eureka
      # Flag to say that, when guessing a hostname, the IP address of the server should be used in preference to the hostname reported by the OS.
      # default: false
      #   当猜测hostname时, 是否优先使用IP地址
      prefer-ip-address: ${EUREKA_INSTANCE_PREFERIPADDRESS:false}
    #  registry:
    #    # Value used in determining when leases are cancelled, default to 1 for standalone. Should be set to 0 for peer replicated eurekas
    #    # default: 1
    #    default-open-for-traffic-count: ${EUREKA_INSTANCE_REGISTRY_DEFAULTOPENFORTRAFFICCOUNT:1}
    #    # default: 1
    #    expected-number-of-renews-per-min: 1
    #  # Gets the absolute status page URL path for this instance.
    #  # The users can provide the statusPageUrlPath if the status page resides in the same instance talking to eureka,
    #  # else in the cases where the instance is a proxy for some other server, users can provide the full URL.
    #  # If the full URL is provided it takes precedence.
    #  # It is normally used for informational purposes for other services to find about the status of this instance.
    #  # Users can provide a simple HTML indicating what is the current status of the instance.
    #  # default: <blank-value>
    #  #   状态页URL, 到Root级别
    #  #status-page-url:
    #  # Gets the relative status page URL path for this instance.
    #  # The status page URL is then constructed out of the hostName and the type of communication - secure or unsecure as specified in securePort and nonSecurePort.
    #  # It is normally used for informational purposes for other services to find about the status of this instance.
    #  # Users can provide a simple HTML indicating what is the current status of the instance.
    #  # default: /info
    #  #   状态页URL的ContextPath
    #  status-page-url-path: /info
    
    eureka.server:
    #  a-s-g-cache-expiry-timeout-ms: 0
    #  a-s-g-query-timeout-ms: 300
    #  a-s-g-update-interval-ms: 0
    #  a-w-s-access-id:
    #  a-w-s-secret-key:
    #  #   是否批量复制
    #  batch-replication: false
    #  binding-strategy:
    #  #   Non-positive
    #  #delta-retention-timer-interval-in-ms: 0
    #  disable-delta: false
    #  disable-delta-for-remote-regions: false
    #  disable-transparent-fallback-to-other-region: false
    #  e-i-p-bind-rebind-retries: 3
    #  e-i-p-binding-retry-interval-ms: 0
    #  e-i-p-binding-retry-interval-ms-when-unbound: 0
    #  enable-replicated-request-compression: false
      enable-self-preservation: ${EUREKA_SERVER_ENABLESELFPRESERVATION:true}
    #  #   Non-positive
    #  #eviction-interval-timer-in-ms: 0
    #  g-zip-content-from-remote-region: true
    #  json-codec-name:
    #  list-auto-scaling-groups-role-name: ListAutoScalingGroups
    #  log-identity-headers: true
    #  max-elements-in-peer-replication-pool: 10000
    #  max-elements-in-status-replication-pool: 10000
    #  #   单位分钟, 节点间负责复制信息的线程的最大空闲时间
    #  max-idle-thread-age-in-minutes-for-peer-replication: 15
    #  #   单位分钟, 节点间负责复制status的线程的最大空闲时间
    #  max-idle-thread-in-minutes-age-for-status-replication: 10
    #  #   复制信息的最大线程数
    #  max-threads-for-peer-replication: 20
    #  #   复制status的最大线程数
    #  max-threads-for-status-replication: 1
    #  #   复制信息的最大时长
    #  max-time-for-replication: 30000
    #  #   复制信息的最小线程数
    #  min-threads-for-peer-replication: 5
    #  #   复制status的最小线程数
    #  min-threads-for-status-replication: 1
    #  number-of-replication-retries: 5
    #  #   Non-positive
    #  #peer-eureka-nodes-update-interval-ms: 0
    #  #   Non-positive
    #  #peer-eureka-status-refresh-time-interval-ms: 0
    #  #   单位ms, 节点间连接超时
    #  peer-node-connect-timeout-ms: 200
    #  #   单位s, 节点间连接空闲超时
    #  peer-node-connection-idle-timeout-seconds: 30
    #  #   单位ms, 节点间read超时
    #  peer-node-read-timeout-ms: 200
    #  #   节点总连接数上限
    #  peer-node-total-connections: 1000
    #  #   节点与单个主机之间的连接数上限
    #  peer-node-total-connections-per-host: 500
    #  prime-aws-replica-connections: true
    #  #   org.springframework.core.env.PropertyResolver
    #  #property-resolver:
    #  rate-limiter-burst-size: 10
    #  rate-limiter-enabled: false
    #  rate-limiter-full-fetch-average-rate: 100
    #  rate-limiter-privileged-clients:
    #  rate-limiter-registry-fetch-average-rate: 500
    #  rate-limiter-throttle-standard-clients: false
    #  registry-sync-retries: 0
    #  registry-sync-retry-wait-ms: 0
    #  #   a map
    #  #remote-region-app-whitelist:
    #  remote-region-connect-timeout-ms: 1000
    #  remote-region-connection-idle-timeout-seconds: 30
    #  remote-region-fetch-thread-pool-size: 20
    #  remote-region-read-timeout-ms: 1000
    #  remote-region-registry-fetch-interval: 30
    #  remote-region-total-connections: 1000
    #  remote-region-total-connections-per-host: 500
    #  remote-region-trust-store:
    #  remote-region-trust-store-password: changeit
    #  remote-region-urls:
    #  #   a map
    #  #remote-region-urls-with-name:
      renewal-percent-threshold: ${EUREKA_SERVER_RENEWALPERCENTTHRESHOLD:0.25}
    #  #   Non-positive
    #  #renewal-threshold-update-interval-ms: 0
    #  response-cache-auto-expiration-in-seconds: 180
    #  #   Non-positive
    #  #response-cache-update-interval-ms: 0
    #  retention-time-in-m-s-in-delta-queue: 0
    #  route53-bind-rebind-retries: 3
    #  route53-binding-retry-interval-ms: 0
    #  route53-domain-t-t-l: 30
    #  sync-when-timestamp-differs: true
    #  use-read-only-response-cache: true
    #  wait-time-in-ms-when-sync-empty: 0 # set to 0 will break cluster
    #  xml-codec-name:
    
    logging:
      config: classpath:log4j2-spring.xml
      #file: ${LOG_FILE:${CONTAINER_HOST_NAME:${spring.cloud.client.hostname:${spring.application.name}-${server.port}}}}.log
      #path: ${LOG_PATH:${user.dir}/data/logs/${spring.application.name}}
      level:
        jndi: ${LOGGING_LEVEL_ROOT:INFO}
    
        org.springframework.beans.factory.annotation.InjectionMetadata: ${LOGGING_LEVEL_ROOT:INFO}
        org.springframework.beans.factory.support.DefaultListableBeanFactory: ${LOGGING_LEVEL_ROOT:INFO}
        org.springframework.core.env.MutablePropertySources: ${LOGGING_LEVEL_ROOT:INFO}
        org.springframework.core.env.PropertySourcesPropertyResolver: ${LOGGING_LEVEL_ROOT:INFO}
        org.springframework.jndi: ${LOGGING_LEVEL_ROOT:INFO}
        org.springframework.core.type.classreading.AnnotationAttributesReadingVisitor: INFO
        org.springframework.web.context.support.StandardServletEnvironment: ${LOGGING_LEVEL_ROOT:INFO}
        org.springframework.security: ${LOGGING_LEVEL_ROOT:INFO}
        root: ${LOGGING_LEVEL_ROOT:INFO}
    
    management:
      endpoint:
        shutdown.enabled: ${MANAGEMENT_ENDPOINT_SHUTDOWN_ENABLED:true}
        health:
          show-details: ${MANAGEMENT_ENDPOINT_HEALTH_SHOWDETAILS:WHEN_AUTHORIZED}
          roles: ${MANAGEMENT_ENDPOINT_HEALTH_ROLES:ACTUATOR}
      endpoints:
        web: # since spring-boot 2.x
          base-path: ${MANAGEMENT_ENDPOINTS_WEB_BASEPATH:/} # default: /actuator, management.context-path deprecated since spring-boot 2.x
          exposure:
            include: "${MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE:*}"
            exclude: "${MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_EXCLUDE:}"
    
    server.port: ${SERVER_PORT:8761}
    
    spring:
      aop.auto: false
      application:
        # every instance in cluster must ues same spring.application.name
        # Peer Awareness Mode: 'eureka-cluster'
        # Standalone Mode: 'standalone.eureka'
        name: ${SPRING_APPLICATION_NAME:standalone.eureka}
        # bug: https://github.com/spring-cloud/spring-cloud-netflix/issues/788
      cloud:
        inetutils:
          preferred-networks: ${SPRING_CLOUD_INETUTILS_PREFERREDNETWORKS:^192.168..+, ^172.30..+, ^10..+}
          ignored-interfaces: ${SPRING_CLOUD_INETUTILS_IGNOREDINTERFACES:^[a-z]?tun[0-9]*, ^awdl[0-9]*, ^lo[0-9]*}
    
      security:
        enabled: ${SPRING_SECURITY_ENABLED:false}
        user:
          name: ${SPRING_SECURITY_USER_NAME:user}
          password: ${SPRING_SECURITY_USER_PASSWORD:user_pass}
          roles: ${SPRING_SECURITY_USER_ROLES:ACTUATOR, ADMIN, SUPERUSER, USER}
    
    
    ---
    spring:
      profiles: port_nonsecure
    
    eureka.instance:
    #  # Get the unique Id (within the scope of the appName) of this instance to be registered with eureka.
    #  # default: <blank-value>
    #  #   instance的id, 区分同一应用的不同实例
    #  #   eureka.instance.instance-id affect Status->instances's url text (not href) value on dashboard
    #  #   or spring.cloud.client.ip-address if eureka.instance.prefer-ip-address=true
    #  #   other possible values:
    #  #     ${spring.application.name}:${spring.cloud.client.ip-address}:${EUREKA_INSTANCE_NONSECUREPORT:${SERVER_PORT:8761}}:${random.value}
    #  #     ${spring.application.name}:${spring.cloud.client.hostname}:${EUREKA_INSTANCE_NONSECUREPORT:${SERVER_PORT:8761}}:${random.value}
    #  instance-id: ${spring.application.name}:${spring.cloud.client.hostname}:${EUREKA_INSTANCE_NONSECUREPORT:${SERVER_PORT:8761}}:${random.value}
    #  # Gets the absolute health check page URL for this instance.
    #  # The users can provide the healthCheckUrlPath if the health check page resides in the same instance talking to eureka,
    #  # else in the cases where the instance is a proxy for some other server, users can provide the full URL. If the full URL is provided it takes precedence.
    #  # It is normally used for making educated decisions based on the health of the instance - for example,
    #  # it can be used to determine whether to proceed deployments to an entire farm or stop the deployments without causing further damage.
    #  # The full URL should follow the format http://${eureka.hostname}:7001/ where the value ${eureka.hostname} is replaced at runtime.
    #  # default: <blank-value>
    #  #   健康检查URL, 到Root级别(HTTP)
    #  health-check-url: ${EUREKA_INSTANCE_HEALTHCHECKURL:}
    #  # Gets the metadata name/value pairs associated with this instance. This information is sent to eureka server and can be used by other instances.
    #  # default: <blank-value>
    #  #   实例元数据
    #  #metadataMap:
    #    #hostname: ${EUREKA_INSTANCE_HOSTNAME:standalone.eureka}
    #    #prot: ${EUREKA_INSTANCE_NONSECUREPORT:8761}
    #    #instanceId: ${spring.cloud.client.hostname}:${spring.application.name}:${EUREKA_INSTANCE_NONSECUREPORT:${SERVER_PORT:8761}}
    #    # or spring.cloud.client.ip-address if eureka.instance.prefer-ip-address=true
    #    #instanceId: ${spring.cloud.client.ip-address}:${spring.application.name}:${EUREKA_INSTANCE_NONSECUREPORT:${SERVER_PORT:8761}}
      # Get the non-secure port on which the instance should receive traffic.
      # default: 80
      #   eureka.instance.non-secure-port affect Status->instances's url href (not text) value on dashboard
      non-secure-port: ${EUREKA_INSTANCE_NONSECUREPORT:8761}
      # Indicates whether the non-secure port should be enabled for traffic or not.
      # default: true
      non-secure-port-enabled: true
      # Gets the virtual host name defined for this instance.
      # This is typically the way other instance would find this instance by using the virtual host name.
      # Think of this as similar to the fully qualified domain name, that the users of your services will need to find this instance.
      # default: unknown
      #virtual-host-name: unknown
      secure-port-enabled: false
    
    ---
    spring:
      profiles: port_secure
    
    eureka.instance:
      non-secure-port-enabled: false
    #  instance-id: ${spring.cloud.client.hostname}:${spring.application.name}:${EUREKA_INSTANCE_SECUREPORT:${SERVER_PORT:8761}}:${random.value}
    #  # Gets the absolute secure health check page URL for this instance.
    #  # The users can provide the secureHealthCheckUrl if the health check page resides in the same instance talking to eureka,
    #  # else in the cases where the instance is a proxy for some other server, users can provide the full URL.
    #  # If the full URL is provided it takes precedence.
    #  # It is normally used for making educated decisions based on the health of the instance - for example,
    #  # it can be used to determine whether to proceed deployments to an entire farm or stop the deployments without causing further damage.
    #  # The full URL should follow the format http://${eureka.hostname}:7001/ where the value ${eureka.hostname} is replaced at runtime.
    #  # default: <blank-value>
    #  #   健康检查URL, 到Root级别(HTTPS)
    #  secure-health-check-url: ${EUREKA_INSTANCE_SECUREHEALTHCHECKURL:}
      # Indicates whether the secure port should be enabled for traffic or not.
      # default: false
      #   是否启用HTTPS
      secure-port-enabled: true
      # Get the Secure port on which the instance should receive traffic.
      # default: 443
      #   HTTPS端口
      secure-port: ${EUREKA_INSTANCE_SECUREPORT:8761}
      # Gets the secure virtual host name defined for this instance.
      # This is typically the way other instance would find this instance by using the secure virtual host name.
      # Think of this as similar to the fully qualified domain name, that the users of your services will need to find this instance.
      # default: unknown
      #secure-virtual-host-name: unknown
    
    ---
    spring:
      profiles: manual_ip_hostname
    
    spring.cloud:
      client:
        hostname: ${SPRING_CLOUD_CLIENT_HOSTNAME:}
        ip-address: ${SPRING_CLOUD_CLIENT_IPADDRESS:}
    
    ---
    spring:
      profiles: peer_awareness
    
    spring.application:
      name: ${SPRING_APPLICATION_NAME:eureka-cluster}
    
    eureka.client:
      fetch-registry: ${EUREKA_CLIENT_FETCHREGISTRY:true}
      register-with-eureka: ${EUREKA_CLIENT_REGISTERWITHEUREKA:true}
    
    eureka.instance:
      appname: ${SPRING_APPLICATION_NAME:eureka-cluster}
    
    ---
    spring:
      profiles: standalone
    
    spring.application:
      name: ${SPRING_APPLICATION_NAME:standalone.eureka}
    
    eureka.client:
      fetch-registry: ${EUREKA_CLIENT_FETCHREGISTRY:false}
      register-with-eureka: ${EUREKA_CLIENT_REGISTERWITHEUREKA:false}
    
    eureka.instance:
      appname: ${SPRING_APPLICATION_NAME:standalone.eureka}
    
    ---
    spring.profiles: develop.env
    
    ---
    spring.profiles: it.env
    
    ---
    spring.profiles: staging.env
    
    ---
    spring.profiles: production.env
    #spring.profiles.include:
    #- port.nonsecure

    使用这种方式的优缺点

    优点:

    • 这种方法使容器在配置方面更具动态性。
    • 集群可以共用一个JAR包来运行,通过容器来配置。

    缺点:

    • 在单容器中配置是固定的,无法便捷的切换。

    注册中心安全认证

    注册中心的页面是直接就能访问的,这肯定不是我们所希望的,所以需要添加安全机制进行保护,这里需要用到依赖 spring-boot-starter-security 

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    配置文件增加 spring.security.user.name 和 spring.security.user.password 配置,修改注册中心地址:

    eureka:
      client:
        service-url:
          defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@192.168.1.254:9010/eureka/ # 注册中心地址
        register-with-eureka: false # 是否注册到注册中心
        fetch-registry: false # 是否拉取服务列表
      server:
        enable-self-preservation: true # 是否开启注册中心保护机制
        eviction-interval-timer-in-ms: 60000 # 服务清理间隔,毫秒
      instance:
        prefer-ip-address: true # 是否使用IP地址广播服务
        lease-renewal-interval-in-seconds: 30 # 服务租约时间,秒
        lease-expiration-duration-in-seconds: 90 # 间隔多久时间没有发送心跳,认为服务不可用,秒
    
    spring:
      # 服务设置
      application:
        name: server-eureka
      # 安全机制
      security:
        user:
          name: eureka
          password: 123456
    
    # 服务设置
    server:
      port: 9010

    使用此组件,安全是实现了,访问注册中心页面,需要登录用户名和密码了,但是问题也出现了,客户端服务一直注册不上去。我查找资料给出的解决方案是禁用 security 的 csrf,下面是处理方案,但是我使用此方案并不生效

    @EnableWebSecurity
        static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                super.configure(http);//加这句是为了访问eureka控制台和/actuator时能做安全控制
                http.csrf().disable();
            }
        }

    上面的方案我使用不生效,我使用下面的方案解决的:

    package com.microview.servereureka.basic;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.password.NoOpPasswordEncoder;
    
    /**
     * 注册中心basic认证
     */
    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Value("${spring.security.user.name}")
        private String username;
    
        @Value("${spring.security.user.password}")
        private String password;
    
        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                    .passwordEncoder(NoOpPasswordEncoder.getInstance())
                    .withUser(username).password(password)
                    .authorities("ADMIN");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .csrf()
                    .disable()
                    .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                    .httpBasic();
        }
    }

    容器宿主机IP注册

    由于所有的项目都运行在 Docker 容器中,这就导致客户端注册到注册中心的 IP 地址为容器的虚拟 IP,无法通过外部访问,这里的解决方案是构建容器时候设置容器的网络模式为桥接模式。

    docker-compose.yml 中配置 network_mode: "bridge" 

      ################ spring-cloud-eureka ##############
      cloud_eureka:
        image: ${REGISTRY_URL}/${REGISTRY_NAMESPACE}/${CLOUD_EUREKA_NAME}:${CLOUD_EUREKA_VERSION}
        container_name: ${CLOUD_EUREKA_CONTAINER_NAME}
        hostname: ${CLOUD_EUREKA_CONTAINER_NAME}
        ports:
        - "${CLOUD_EUREKA_PORT}:9010"
        volumes:
        - ${CLOUD_EUREKA_DATA}:/data/:rw
        - ${CLOUD_EUREKA_LOGS}:/data/logs/:rw
        - ${SH_DIR}:/usr/local/sh/:rw
        tty: true
        restart: always
        network_mode: "bridge"

    客户端配置文件中相关配置(192.168.1.254 为宿主机IP地址):

    eureka:
      client:
        service-url:
          defaultZone: http://eureka:123456@192.168.1.254:9010/eureka/
      instance:
        instance-id: ${eureka.instance.ip-address}:${server.port}
        ip-address: 192.168.1.254
        prefer-ip-address: true

    这样注册到注册中心的IP地址就是宿主机的IP了。

    同主机多 eureka 需要特别注意:eureka 注册地址主机相同(相同的IP地址或 hostname)不会互相同步注册信息。

    my spring cloud exampleshttps://github.com/BNDong/spring-cloud-examples

    参考资料

    https://blog.csdn.net/quanqxj/article/details/80592231

    https://github.com/spring-cloud/spring-cloud-netflix/issues/2754

    https://www.oschina.net/question/556985_2273961

    https://blog.csdn.net/qq_36148847/article/details/79427878

    https://www.youtube.com/watch?v=tFw8Nm8meqI

    https://dantehranian.wordpress.com/2015/03/25/how-should-i-get-application-configuration-into-my-docker-containers/

    后记

    写这篇随笔时候不知道为什么想到了看过的一个短片《断崖》,看的时候真的感受到了女主的绝望和无助。感觉自己就像女主一样,我在自己技术水平的坑里努力的爬着,好的是我爬出来了,坏的是外面还有一个更大的坑!!!人生路漫漫,且爬且珍惜!感谢阅读!

  • 相关阅读:
    Spring Security(06)——AuthenticationProvider
    Spring Security(05)——异常信息本地化
    Spring Security(04)——认证简介
    Spring Security(03)——核心类简介
    Spring Security(02)——关于登录
    Spring Security(01)——初体验
    核心服务
    技术概述
    Security命名空间配置
    Spring Security
  • 原文地址:https://www.cnblogs.com/bndong/p/10037197.html
Copyright © 2020-2023  润新知