代码地址:https://github.com/lmchuyang/huyang/tree/master/springBootCloud
接触微服务不久,一直想写套集群服务注册的应用场景,正好项目空闲期,就来搭建一个eureka服务治理框架
主要分为两个角色 eureka server和eureka client 从整个结构来看, 可以分为三部分, 服务注册与发现,生产者,消费者或是调用者,集成的时候,这些微服务可以写在一个项目,多个配置文件也可以,我这边了直观简洁,复制了项目修改不同的配置
大致图是这样,有不对的地方大家可以指出,
这是整个项目结构
2 创建服务注册中心项目
启动服务很简单 我们写一个启动类,加上@EnableEurekaServer注解即可。
@SpringBootApplication
@EnableEurekaServer
@EnableDiscoveryClient
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
pom.xml文件的依赖,这里我采用Spring boot的版本用2.0.3.RELEASE 官方默认版本配置,因为项目是自己需要打包到容器去运行,所以加了docker 插件来打包生成容器,如果不需要的话, 可以把容器那些插件删掉,不影响项目
然后是application.yml文件:注释比较多, 不想看的可以删掉,不影响啥, 我是为了方面以后查看
server:
port: 5011
spring:
application:
name: euraka-server
eureka:
client:
registerWithEureka: true
fetchRegistry: true
server:
enable-self-preservation: false
serviceUrl:
defaultZone: http://peer2:5012/eureka/,http://peer3:5013/eureka/
instance:
hostname: peer1
#peer1、peer2和peer3需要在hosts文件中设置为127.0.0.1,在生产环境中可以写真实的域名
metadataMap:
instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
#1 这里peer1、peer2和peer3需要在hosts文件中设置为127.0.0.1,在生产环境中可以写真实的域名
#2 注册中心集群模式,一定要自身注册到服务上,被其它节点发现registerWithEureka: true
#如果是单eureka server的环境,就将eureka.client.serviceUrl.defaultZone设置为本机的服务注册地址,
#同时需要设置eureka.client.registerWithEureka和eureka.client.fetchRegistry为false,以防止自己注册自己,集群的话设置为true。同时设置应用名为eureka-server
# Eureka Server会将当前的实例注册信息保护起来,同时提示这个警告
#3 spring.application.name或eureka.instance.appname必须一致;否则unavailable-replicas 界面显示是不可到达,或服务不可用
#4 enable-Self-Preservation 自我保护模式, Eureka Server在运行期间,会统计心跳失败的比例在15分钟之内是否
#低于85%,如果出现低于的情况(在单机调试的时候很容易满足,实际在生产环境上通常是由于网络不稳定导致),Eureka Server会将当前的实例注册信息保护起来,
#同时提示这个警告。保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,
#Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)
特别提示下:
这里peer1、peer2和peer3需要在hosts文件中设置为127.0.0.1,在生产环境中可以写真实的域名
设置端口为5011,当前实例主机名为peer1 eureka.client.serviceUrl.defaultZone为另外两台eureka server的服务注册地址
另外两台eureka server的pom.xml文件一样,除了修改端口 application.yml文件中的eureka.client.serviceUrl.defaultZone分别设置为另外两个eureka server的服务地址 ,另外两台的端口是5012 主机名peer2 5013和peer3
pom.xml文件依赖 比服务注册多一个包,并且跟springBoot1.5版本差距还是很大,都 在netflix 文件里
配置文件也与服务注册中心有所不同。
server:
port: 5022
eureka:
client:
serviceUrl:
defaultZone: http://peer1:5011/eureka/
healthcheck:
enabled: true
lease:
duration: 5
instance:
preferIpAddress: true
spring:
application:
name: springCloudEurakaProvider
#两个生产者应用史是一样的,这样微服务之间调用的时候只以做负载均衡,无需指定某个应用名
#logging:
# level:
# org.exampledriven.eureka.customer.shared.CustomerServiceFeignClient: FULL
#lease 租期时间,不定时发送心跳包消息,如果长时间未能更新租期时间,服务就为抛弃该服务实例,注册中心会当成无用服务
就写个最简单的hello world式的restful接口
@RestController}
现在springCloudEurakaProvider1基本完成 了, springCloudEurakaProvider2跟这个一样,只需要改下配置文件 端口设置成5023 defaultZone配置可以在三台中任意选 一个
server:
port: 5023
eureka:
client:
serviceUrl:
defaultZone: http://peer2:5012/eureka/
healthcheck:
enabled: true
lease:
duration: 5
instance:
preferIpAddress: true
spring:
application:
name: springCloudEurakaProvider
#两个生产者应用史是一样的,这样微服务之间调用的时候只以做负载均衡,无需指定某个应用名
#logging:
# level:
# org.exampledriven.eureka.customer.shared.CustomerServiceFeignClient: FULL
#lease 租期时间,不定时发送心跳包消息,如果长时间未能更新租期时间,服务就为抛弃该服务实例,注册中心会当成无用服务
与之前的消息生产者一样,需要说明的是,1.5版本要加rabbon 的依赖,2.0.3版本不需要了,自动依赖一个人种模式的负载均衡Resttempte+Rabbon,和 Feign。默认是轮询的方式。
需要修改的也只有 配置文件
server:
port: 5080
eureka:
client:
serviceUrl:
defaultZone: http://peer1:5011/eureka/
healthcheck:
enabled: true
lease:
duration: 5
instance:
preferIpAddress: true
spring:
application:
name: springCloudEurakaConsumer
#logging:
# level:
# org.exampledriven.eureka.customer.shared.CustomerServiceFeignClient: FULL
#lease 租期时间,不定时发送心跳包消息,如果长时间未能更新租期时间,服务就为抛弃该服务实例,注册中心会当成无用服务
启动类,这里一样加上EnableEurekaClient的注解。同时创建RestTemplate的bean,再加上EnableFeignClients后面两种负载均衡一起做,加上LoadBalanced注解用于负载均衡
@SpringBootApplication
@Configuration
@EnableEurekaClient
@EnableDiscoveryClient
@EnableFeignClients
public class DemoServerApplication {
public static void main(String[] args) {
SpringApplication.run(DemoServerApplication.class, args);
}
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
接下来是具体的消费类的代码 因为用到Feign方式调用微服务, 所以写了个接口
@RestController
public class CustomerController {
//微服务之间调用的方式有两种,RestTemplate+ribbon 实现负载均衡,第二种是Feign Client
//spring-cloud-starter-ribbon的依赖用于客户端负载均衡,默认是轮询的方式。
@Autowired
RestTemplate restTemplate;
@GetMapping("/helloCustomer")
public String helloCustomer(){
return restTemplate.getForEntity("http://springCloudEurakaProvider/hello", String.class).getBody();
}
@GetMapping("/customerWorld")
public String worldCustomer(){
return restTemplate.getForEntity("http://springCloudEurakaProvider/world", String.class).getBody();
}
//使用Spring Netflix Feign Client实现的REST消费Web应用,本地服务调用远程微服务的接口
@Autowired
private GreetingClient greetingClient;
@RequestMapping("/get-greeting")
public String greeting(Model model) {
Map
parpm.put("name", "lmc");
parpm.put("test", "demo");
String message = greetingClient.greeting(parpm.toString()); //以字符串方式传参数
return message+":传参数";
}
}
Feign Client 调用微服务的接口 GreetingClient
//Feign Client 调用微服务程序,接口方式实现,可以很好的将微服务分开,松耦合
@FeignClient("springCloudEurakaProvider")
public interface GreetingClient {
/**
* 这里有两个坑需要注意:
*
* 1、这里需要设置请求的方式为 RequestMapping 注解,用 GetMapping 注解是运行不成功的,即 GetMapping 不支持。
*
* 2、注解 PathVariable 里面需要填充变量的名字,不然也是运行不成功的。
* 3、这一方法主要就是为了绑定Controller里,访问url的方法,控制层通过方法去请求找到相应的URL方法
* 通过接口方式绑定远程微服务
*/
/* @RequestMapping(value="/greeting",method = RequestMethod.POST)
String greeting(JSONObject parpam);*/
@PostMapping(value="/greeting")//传参数的方式调用
String greeting(String str);
}
到这里就基本结束简单的配置信息,开始测试能不能跑通了,实践过程中由于版本和环境的问题, 不知道坑了多少次,都 是一步步探着坑走过来的,
再查看服务注册中心的相关信息,访问peer1:1111或者peer2:1112或者peer3:1113可以查看。
可以看到服务已经注册上了
三个服务注册中心,两个服务生产者, 一个服务消费都 ,都 在这上面运行,这样说明一切正常了
最后验证服务是否调用成功,访问http://localhost:5080/customerWorld 成功得到如下结果:
再然后可以看看负载均衡,在地址栏多次刷新,查看打印输出的信息会得到不同实例输出的结果,
说明 负载均衡正常
到这里就全部结束了,如有问题可以直接下面留言,虽然还有很多不懂的原理,希望能和大家一起探讨