搭建简单的微服务工程(Eureka)

一、微服务工程搭建

1. 注册中心搭建

工程目录:

pom.xml :

<!--1. 引入springboot父工程 -->
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.2.2.RELEASE</version>
	<relativePath/> 
</parent>

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<maven.compiler.source>1.7</maven.compiler.source>
	<maven.compiler.target>1.7</maven.compiler.target>
	<!--2. springcloud版本-->
	<spring-cloud.version>Hoxton.SR1</spring-cloud.version>

</properties>

 <dependencies>
	<!--3. Eureka服务端启动器导入-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
	</dependency>

</dependencies>

<!--4. springcloud的依赖仓库导入 -->
<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>${spring-cloud.version}</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

application.properties:

server.port=8763
eureka.instance.hostname=localhost

#是否注册到eureka
eureka.client.registerWithEureka=false
#是否从eureka中拉取注册信息
eureka.client.fetchRegistry=false
##暴露eureka服务的地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

#自我保护模式,当出现出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除,默认为true
eureka.server.enable-self-preservation=true

启动类:

package com.lic;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
//开启eureka客户端功能
@EnableEurekaServer
public class EurekaApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class,args);
    }
}

2. 服务提供方

工程目录:

pom.xml

<!--1. 引入springboot父工程 -->
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.2.2.RELEASE</version>
	<relativePath/>
</parent>

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<maven.compiler.source>1.7</maven.compiler.source>
	<maven.compiler.target>1.7</maven.compiler.target>
	<!--2. springcloud版本-->
	<spring-cloud.version>Hoxton.SR1</spring-cloud.version>

</properties>

<dependencies>
	<!--3.1 引入spring-boot-starter-web依赖(注册方需要发送http请求)-->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<!--3.2 Eureka客户端启动器导入-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>
</dependencies>

<!--4. springcloud的依赖仓库导入 -->
<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>${spring-cloud.version}</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

application.properties:

spring.application.name=springcloud-eureka-client-provider
server.port=8084
eureka.client.serviceUrl.defaultZone=http://localhost:8763/eureka/

启动类:

package com.lic;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
//开启Eureka客户端功能
@EnableEurekaClient
public class EurekaClientProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientProviderApplication.class,args);
    }
}

测试类:

package com.lic.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @RequestMapping("/queryUser")
    public String queryUser(){
        System.out.println("springcloud-eureka-client-provider: Hello World");
        return "springcloud-eureka-client-provider: Hello World";
    }
}

3. 服务消费方

工程目录:

pom.xml

<!--1. 引入springboot父工程 -->
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.2.2.RELEASE</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<maven.compiler.source>1.7</maven.compiler.source>
	<maven.compiler.target>1.7</maven.compiler.target>
	<!--2. springcloud版本-->
	<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
</properties>


<dependencies>
	<!--3.1 引入spring-boot-starter-web依赖(注册方需要发送http请求)-->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<!--3.2 Eureka客户端启动器导入-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>
</dependencies>

	<!--4. springcloud的依赖仓库导入 -->
<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>${spring-cloud.version}</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

application.properties:

spring.application.name=springcloud-eureka-client-consumer
server.port=8085
eureka.client.serviceUrl.defaultZone=http://localhost:8763/eureka/

启动类:

package com.lic;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
//开启Eureka客户端功能
@EnableEurekaClient
public class EurekaClientConsumerApplication {

    @Bean
    //负载均衡注解
    @LoadBalanced
    RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientConsumerApplication.class);
    }
}

测试类:

================================ controller层 =================================
package com.lic.controller;

import com.lic.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("queryUser")
    public String queryUser(){
        return userService.queryContent();
    }

}


================================= service层 ===================================

package com.lic.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
public class UserServiceImpl implements UserService{

    public static String SERVIER_NAME = "springcloud-eureka-client-provider";

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public String queryContent() {
        String result = restTemplate.getForObject("http://"+
                SERVIER_NAME + "/queryUser",String.class);
        return result;
    }
}

4. 测试

1.1 浏览器访问Eureka监控中心: http://localhost:8763/

1.2 启动多个Eureka服务提供方工程:

2. 浏览器访问Eureka服务提供方: http://localhost:8085/user/queryUser

3. Eureka服务提供方控制台输出:

二、Eureka用户认证 

连接到 eureka 的时候需要带上连接的用户名和密码

Eureka服务端配置:

1. pom文件中添加启动器:

<!-- 5. Eureka用户认证启动器 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. 代码配置, 关闭csrf验证:

package com.lic;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //关闭csrf
        http.csrf().disable();
        //开启认证: URL格式登录必须是httpBasic
       http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
    }
}

3. application.properties配置:

#开启basic校验, 设置登录用户名密码
security.basic.enabled=true
spring.security.user.name=admin
spring.security.user.password=admin

Eureka客户端配置:

#与 eureka 连接的时候要带上用户名密码
eureka.client.serviceUrl.defaultZone=http://admin:admin@localhost:8763/eureka/

 三、服务续约保活

当客户端启动想 eureka 注册了本身服务列表后, 需要隔段时间发送一次心跳给 eureka 服务端来证明自己还活着, 当 eureka 收到这个心跳请求后才会知道客户端还活着, 才会维护该客户端的服务列表信息; 一旦因为某些原因导致客户端没有按时发送心跳给 eureka 服务端, 这时候 eureka 可能会认为你这个客户端已经挂了, 它就有可能把该服务从服务列表中删除掉。

Eureka服务端配置:

#自我保护模式,当出现出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除,默认为true
eureka.server.enable-self-preservation=true
#Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来
eureka.server.renewal-percent-threshold=0.85
#eureka server 清理无效节点的时间间隔,默认 60000 毫秒,即 60 秒
eureka.server.eviction-interval-timer-in-ms=60000

Eureka客户端配置:

#服务续约,心跳的时间间隔
eureka.instance.lease-renewal-interval-in-seconds=10
#如果从前一次发送心跳时间起,30 秒没接受到新的心跳,就剔除服务
eureka.instance.lease-expiration-duration-in-seconds=30
#表示 eureka client 间隔多久去拉取服务注册信息,默认为 30 秒
eureka.client.registry-fetch-interval-seconds=30

四、Eureka健康监测

Eureka 默认的健康检测只是你校验服务连接是否是 UP 还是 DOWN 的,  然后客户端只会调用状态为 UP 状态的服务, 但是有的情况下, 虽然服务连接是好的, 但是有可能这个服务的某些接口不是正常的, 可能由于需要连接 Redis, mongodb 或者 DB 有问题导致接口调用失败, 所以理论上服务虽然能够正常调用,  但是它不是一个健康的服务;  所以我们就有必要对这种情况做自定义健康检测

Eureka客户端配置:

1. application.properties配置:

#开启健康检测
eureka.client.healthcheck.enabled=true

2. 自定义健康监测器:

package com.lic.health;

import com.lic.controller.UserController;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.Status;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EurekaClientHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        //根据健康监测返回的结果判断当前服务状态
        if (UserController.healthChecked){
            return new Health.Builder(Status.UP).build();
        }else{
            return new Health.Builder(Status.DOWN).build();
        }
    }
}
package com.lic.controller;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    public static boolean healthChecked = true;

    @RequestMapping("healthCheck/{health}")
    public void healthCheck(@PathVariable boolean health){
        //todo: 针对服务中的某些接口进行检测, 给出健康状态的判断
        healthChecked = health;
    }
}

3. pom依赖添加:

<!-- 5. 健康监测的jar包 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

查看服务健康状态: http://localhost:8084/actuator/health 

修改服务的健康状态: http://localhost:8084/healthCheck/false

五、服务下线

比如有些情况是服务主机意外宕机了, 也就意味着服务没办法给 eureka 心跳信息了, 但是eureka 在没有接受到心跳的情况下依赖维护该服务 90s, 在这 90s 之内可能会有客户端调用到该服务, 这就可能会导致调用失败; 所以我们必须要有一个机制能手动的立马把宕机的服务从 eureka 服务列表中清除掉, 避免被服务调用方调用到。

这个接口是调用 eureka 服务端的接口: http://localhost:8763/eureka/apps/EUREKA-CLIENT-PROVIDER/localhost:eureka-client-provider:8084

六、Eureka高可用

整个微服务中存在多个 eureka 服务, 每个 eureka 服务都是相互复制的, 会把客户端注册进来的服务复制到 eureka 集群中的其他节点里面来,  其实简单来说就是 eureka 每个节点相互复制;

Eureka服务端配置:

1. application-8671.properties配置:

server.port=8761
eureka.instance.hostname=eureka8761

#是否注册到eureka
eureka.client.registerWithEureka=true
#是否从eureka中拉取注册信息
eureka.client.fetchRegistry=true
##暴露eureka服务的地址 (当前eureka服务把自己注册到另外一个eureka服务中)
#注意: 如果不配置域名映射(127.0.0.1 ==> eureka8762): eureka.client.serviceUrl.defaultZone=http://admin:admin@localhost:8762/eureka/
eureka.client.serviceUrl.defaultZone=http://admin:admin@eureka8762:8762/eureka/


#开启basic校验, 设置登录用户名密码
security.basic.enabled=true
spring.security.user.name=admin
spring.security.user.password=admin

#自我保护模式,当出现出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除,默认为true
eureka.server.enable-self-preservation=true
#Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来
eureka.server.renewal-percent-threshold=0.85

#eureka server 清理无效节点的时间间隔,默认 60000 毫秒,即 60 秒
eureka.server.eviction-interval-timer-in-ms=60000

2. application-8672.properties配置:

server.port=8762
eureka.instance.hostname=eureka8762

#是否注册到eureka
eureka.client.registerWithEureka=true
#是否从eureka中拉取注册信息
eureka.client.fetchRegistry=true
##暴露eureka服务的地址 (当前eureka服务把自己注册到另外一个eureka服务中)
#注意: 如果不配置域名映射(127.0.0.1 ==> eureka8761): eureka.client.serviceUrl.defaultZone=http://admin:admin@localhost:8761/eureka/
eureka.client.serviceUrl.defaultZone=http://admin:admin@eureka8761:8761/eureka/


#开启basic校验, 设置登录用户名密码
security.basic.enabled=true
spring.security.user.name=admin
spring.security.user.password=admin

#自我保护模式,当出现出现网络分区、eureka在短时间内丢失过多客户端时,会进入自我保护模式,即一个服务长时间没有发送心跳,eureka也不会将其删除,默认为true
eureka.server.enable-self-preservation=true
#Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来
eureka.server.renewal-percent-threshold=0.85

#eureka server 清理无效节点的时间间隔,默认 60000 毫秒,即 60 秒
eureka.server.eviction-interval-timer-in-ms=60000

3. hosts域名映射配置:  
127.0.0.1       eureka8762
127.0.0.1       eureka8761

Eureka客户端配置:

application-cluster.properties配置:

spring.application.name=eureka-client-provider
server.port=8084

#是否注册到eureka
eureka.client.registerWithEureka=true
#是否从eureka中拉取注册信息
eureka.client.fetchRegistry=true
#注意: 如果不配置域名映射(127.0.0.1 ==> eureka8761,127.0.0.1 ==> eureka8762)
#那么: http://admin:admin@localhost:8761/eureka/,http://admin:admin@localhost:8762/eureka/
eureka.client.serviceUrl.defaultZone=http://admin:admin@eureka8761:8761/eureka/,http://admin:admin@eureka8762:8762/eureka/
#hystrix.stream  开放所有的监控接口
management.endpoints.web.exposure.include=*

#feign开启熔断器
feign.hystrix.enabled=true
#开启feign的压缩功能
feign.compression.request.enabled=true
#feign.compression.request.mime-types=text/xml,application/xml,application/json
#feign.compression.request.min-request-size=2048
feign.compression.response.enabled=true

#全局超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
#hystrix.command.<commandKey>作为前缀,默认是采用Feign的客户端的方法名字作为标识
hystrix.command.saveStudent.execution.isolation.thread.timeoutInMilliseconds=6000

#全局ribbon配置
MICRO-ORDER.ribbon.ConnectTimeout=5000

#could not be registered. A bean with that name has already been defined in file
spring.main.allow-bean-definition-overriding=true

启动:

将eureka服务端工程打包 (> mvn package -Dmaven.skiptest=true), 启动(> java -jar springcloud-1.0.0.RELEASE.jar --spring.profiles.active=8762      > java -jar springcloud-1.0.0.RELEASE.jar --spring.profiles.active=8762)

将eureka客户端工程打包 (mvn package -Dmaven.skiptest=true), 启动(> java -jar springcloud-eureka-client-provider-1.0.0.RELEASE.jar --spring.profiles.active=cluster)

注意: 在启动eureka服务时, 由于两个服务会相互注册, 但是如果两个服务没有同时启动完成, 那么启动好的那个服务向另外一个服务注册时会出现未知主机异常, 当两个服务都启动完成后, 就可以正常注册了

eureka8761服务信息:

eureka8762服务信息:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值