spring cloud eureka zuul ribbon hystrix feign config 示例

以前的分布式系统基本上都是基于dubbo,国内现在大多数公司分布式体系这块还都是基于dubbo的。

但最近看到spring cloud 社区  各大论坛比较活跃,很强大的后起之秀,可能一两年后在国内掀起一片热潮。


下面只是针对一些点单独的示例,其实有时间应该整合到一起,做一个完整的示例。

 cloud体系支持了应用微服务的集群负载,后续还需要研究下cloud各部分的集群负载。

在真正的分布式系统中,应该尽量避免单点,否则若是cloud的基础部分,如zuul  config  eureka若是单点,

只有一个出问题,整个分布式系统就完蛋了。


不废话了,进入正题,先看下项目截图


1.  Eureka

使用eureka注册和发现服务,主要maven引入如下资源

   	<dependency>
  		<groupId>org.springframework.cloud</groupId>
  		<artifactId>spring-cloud-starter-eureka-server</artifactId>
  	</dependency>
  	<dependency>
  		<groupId>org.springframework.cloud</groupId>
  		<artifactId>spring-cloud-starter-eureka</artifactId>
  	</dependency>

这里分了三块内容:eureka-server,作为注册服务中心;eureka-provider,服务提供最; eureka-consumer 服务调用者

eureka-server

application.properties

spring.application.name=eureka-server
server.port=2100

eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF

eureka.client.serviceUrl.defaultZone=http://127.0.0.1:${server.port}/eureka/

启动入口

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

@EnableEurekaServer         //开启eureka服务
@SpringBootApplication      //springBoot注解,spring在springBoot基础之上来构建项目
public class EurekaServerApp {

    //spirng boot的标准入口
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApp.class, args);
    }
}
启动后即可通过 http://127.0.0.1:2100/ 访问  看到相关服务信息

eureka-provider

application.properties

spring.application.name=eureka-provider
server.port=2200

logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF


eureka.client.serviceUrl.defaultZone=http://127.0.0.1:2100/eureka/


启动入口

/**
 * @author Administrator
 *
 */
@EnableDiscoveryClient            //通过该注解,实现服务发现,注册
@SpringBootApplication
public class ProviderApp {

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

}

服务

package com.yonyou.student.web;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.yonyou.student.Student;


@RestController
@RequestMapping("/student")
class StudentController {
	
    
	@Value("${server.port}")  
	private String port;  
	
    @RequestMapping("list")
    public List<Student> list() {
    	List<Student> list = new ArrayList<Student>();
    	
    	list.add(new Student(111,"yaoming","156787787823","china shanghai"));
    	list.add(new Student(222,"chenglong","13898687682","china hongkong"));
    	list.add(new Student(333,"lilianjie","187923420023","china beijing"));
    	list.add(new Student(444,port,port,port));
    	
        return list;
    }
    
    
    
}

eureka-consumer

spring.application.name=eureka-consumer
server.port=2300

logging.level.com.netflix.eureka=OFF
logging.level.com.netflix.discovery=OFF


eureka.client.serviceUrl.defaultZone=http://127.0.0.1:2100/eureka/

rest.student=http://eureka-provider
rest.student.list=${rest.student}/student/list

启动入口 和 调用

package com.yonyou;
import java.net.URI;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author Administrator
 *
 */
@EnableDiscoveryClient            //通过该注解,实现服务发现,注册
@SpringBootApplication
public class ConsumerApp {
	
	  /**
     * LoadBalanced 注解表明restTemplate使用LoadBalancerClient执行请求
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        RestTemplate template = new RestTemplate();
        SimpleClientHttpRequestFactory factory = (SimpleClientHttpRequestFactory) template.getRequestFactory();
        factory.setConnectTimeout(3000);
        factory.setReadTimeout(3000);
        return template;
    }
	
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApp.class, args);
    }

}

@RestController
class ServiceInstanceRestController {
	
	@Autowired
	@LoadBalanced
	RestTemplate restTemplate; 
	
    @Autowired
    private DiscoveryClient discoveryClient;

    @RequestMapping("/service-instances/{applicationName}")
    public List<ServiceInstance> serviceInstancesByApplicationName(
            @PathVariable String applicationName) {
        return this.discoveryClient.getInstances(applicationName);
    }

    @RequestMapping("/info")
    public String sayhello() {
        return "client-teacher";
    }
    
    

    // Restful服务对应的url地址  
    @Value("${rest.student.list}")  
    private String restStudentList;  
    
    @Value("${server.port}")  
    private String port;  
    
    
    @RequestMapping("/students")
    public String test() {
    	
//    	ServiceInstance instance = loadBalancer.choose("eureka-client-student");
//    	URI uri = instance.getUri();
    	
    	List list =  restTemplate.getForObject(restStudentList, List.class);
    	
    	return port+" : "+list.toString();
    }
    
    
    
}

去注册中心可以看到 provider 和 consumer已经起来



单独访问 provider

http://127.0.0.1:2200/student/list

访问consumer

http://127.0.0.1:2300/students

consumer调用provider是通过restTemplate实现的,这里的restStudentList就是provider的服务rest地址。这样写感觉不太友好,后面会将通过feign实现。


2. zuul   网关

maven 主要依赖

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-zuul</artifactId>
		</dependency>

properties

   spring.application.name=zuul
    server.port=3100  
      
    zuul.prefix=/gw
    #ignoredServices: '*'
    
      
    #这里的配置表示,访问/baidu/** 直接重定向到http://www.baidu.com  
    zuul.routes.baidu.path=/baidu/**  
    zuul.routes.baidu.url=http://www.baidu.com  
    
    #ribbon.eureka.enabled=false
      
    #反响代理配置  
    #这里的配置类似nginx的反响代理  
    #当请求/api/**会直接交给listOfServers配置的服务器处理  
    #当stripPrefix=true的时候 (http://127.0.0.1:8181/api/user/list -> http://192.168.1.100:8080/user/list)  
    #当stripPrefix=false的时候(http://127.0.0.1:8181/api/user/list -> http://192.168.1.100:8080/api/user/list)  
    zuul.routes.api.path=/api/**
    zuul.routes.api.stripPrefix=true  
    #api.ribbon.listOfServers=127.0.0.1:6060,127.0.0.1:6061
    zuul.routes.api.serviceId=eureka-consumer  
    
      
    #url重写配置  
    #这里的配置,相当于访问/index/** 会直接渲染/home的请求内容(和直接请求/home效果一样), url地址不变  
    zuul.routes.index.path=/index/**  
    zuul.routes.index.url=forward:/home  
    
    
    
    eureka.client.serviceUrl.defaultZone=http://127.0.0.1:2100/eureka/


boot 入口

package com.zybros;
  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;  
  
@EnableZuulProxy  
@SpringBootApplication  
public class ZuulApp  {  
    public static void main( String[] args ) {  
        SpringApplication.run(ZuulApp.class, args);  
    }  
} 

controller

package com.zybros;
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
public class HomeController {  
      
    @RequestMapping("/index")  
    public Object index() {  
        return "index";  
    }  
      
    @RequestMapping("/home")  
    public Object home() {  
        return "home";  
    }  
}  

通过网关 http://127.0.0.1:3100/gw/api/students 可以访问到上面 consumer 的students服务


3. config  配置中心

本示例是基于本地实现的,也可以用 git  svn

config-server

主要依赖

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-config-server</artifactId>
		</dependency>

boot入口

package com.zybros;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.config.server.EnableConfigServer;

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApp {

	public static void main(String[] args) {
		new SpringApplicationBuilder(ConfigServerApp.class).web(true).run(args);
	}

}

properties

spring.application.name=config-server
server.port=1100  
   
# git远程配置
#spring.cloud.config.server.git.uri=http://git.oschina.net/didispace/SpringBoot-Learning/
#spring.cloud.config.server.git.searchPaths=Chapter9-1-4/config-repo
#spring.cloud.config.server.git.username=username
#spring.cloud.config.server.git.password=password
 
# 激活本地配置  Config Server会默认从应用的src/main/resource目录下检索配置文件
# 也可以通过spring.cloud.config.server.native.searchLocations=file:F:/properties/属性来指定配置文件的位置。
spring.profiles.active=native


#URL与配置文件的映射关系如下:
#/{application}/{profile}[/{label}]
#/{application}-{profile}.yml
#/{label}/{application}-{profile}.yml
#/{application}-{profile}.properties
#/{label}/{application}-{profile}.properties
#上面的url会映射{application}-{profile}.properties对应的配置文件,{label}对应git上不同的分支,默认为master。


   


只有一条数据的配置文件

启动后可以通过 http://127.0.0.1:1100/cloud-test.properties 访问到

config-test远程访问配置文件数据

bootstrap.properties

server.port=1200  

#spring.application.name:对应前配置文件中的{application}部分
spring.application.name=cloud
#spring.cloud.config.profile:对应前配置文件中的{profile}部分
spring.cloud.config.profile=dev
#spring.cloud.config.label:对应前配置文件的git分支
spring.cloud.config.label=master
#spring.cloud.config.uri:配置中心的地址
spring.cloud.config.uri=http://127.0.0.1:1100/




 
 

boot启动

package com.zybros;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
public class ConfigTestApp {

	public static void main(String[] args) {
		new SpringApplicationBuilder(ConfigTestApp.class).web(true).run(args);
	}

}

访问配置文件代码

package com.zybros;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RefreshScope
@RestController
class TestController {

	@Value("${from}")
	private String from;

	@RequestMapping("/from")
	public String from() {

		return this.from;
	}

	public void setFrom(String from) {
		this.from = from;
	}

	public String getFrom() {
		return from;
	}

}


 http://127.0.0.1:1200/from

4. feign  为rest服务编写本地接口,这样是为了调用方便,这样的工作一边应该让开发服务的人员提供对应rest的feign接口

feign-server

properties

spring.application.name=feign-server
server.port=4100  
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:2100/eureka/

boot 入口

package com.zybros;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
@EnableDiscoveryClient  
@SpringBootApplication
public class FeignServerApp {

	public static void main(String[] args) {
		new SpringApplicationBuilder(FeignServerApp.class).web(true).run(args);
	}

}
下面的rest服务,需要在调用端通过feign client 编写接口
package com.zybros;

import java.util.Map;

import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RefreshScope
@RestController
class UserController {


	@RequestMapping("/login/{name}")
	public String login(@PathVariable("name") String name,String pwd) {

		return "============ "+name+" "+pwd+" login success ============";
	}
	
	
	@RequestMapping("/login2")
	public String login2(String name,String pwd) {

		return "============ "+name+" "+pwd+" login success ============";
	}

	
	@RequestMapping("/login3")
	public String login3(@RequestBody Map map) {

		return "============ "+map+" login success ============";
	}

	
	@RequestMapping("/login4")
	public String login4(@RequestBody User user) {

		return "============ "+user.getName()+" "+user.getPwd()+" login success ============";
	}
	
	


}


feign-client

spring.application.name=feign-client
server.port=4200  
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:2100/eureka/

针对feign-server暴露的rest服务编写接口,就如同前面说的,这部分接口最好是让开发上面rest服务的人员开发,这样维护统一些。

package com.zybros.user;

import java.util.Map;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;


@FeignClient("feign-server")
public interface UserService {

	@RequestMapping(value ="/login/{name}", method = RequestMethod.GET)
	public String login(@PathVariable("name") String name);
	

	@RequestMapping(value ="/login2", method = RequestMethod.GET)
	public String login2(@RequestParam ("name") String name,@RequestParam ("pwd") String pwd);
	
	
	@RequestMapping(value ="/login3", method = RequestMethod.GET)
	public String login3(@RequestBody Map<String, Object> map);
	
	@RequestMapping(value ="/login4", method = RequestMethod.POST)
	public String login4(@RequestBody User user);
	

}

controller调用feign写的接口,容器为针对接口生成实现类,实现类内部通过restTemplate调用rest服务

package com.zybros.user;

import java.util.HashMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.Maps;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
class UserController {

	@Autowired
	private UserService userService; // 远程服务

	@RequestMapping("/login-test1")
	public String login(String name, String pwd) {
		
		return userService.login(name);

	}
	
	@HystrixCommand(fallbackMethod="fallback2")
	@RequestMapping("/login-test2")
	public String login2(String name, String pwd) {
		
		return userService.login2(name,pwd);

	}
	
	@RequestMapping("/login-test3")
	public String login3(String name, String pwd) {
		 HashMap<String, Object> map = Maps.newHashMap();
		  map.put("name", name);
		  map.put("pwd", pwd);
		return userService.login3(map);

	}
	
	@RequestMapping("/login-test4")
	public String login4(String name, String pwd) {
		return userService.login4(new User(name,pwd));

	}
	
	public String fallback2(String name,String pwd){
		
		return "===== fallback2 ======= "+name+" "+pwd+" login success ============";
		
	}
	 

}

两个启动后访问 http://127.0.0.1:4200/login-test3?name=stone&pwd=123

这就是通过接口访问传map,也可以传其他类型参数


5. hystrix circuit

maven依赖

	<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
		</dependency>


代码还是上面feign-client的代码,其中controller中的login-test2


为了测试,可以试着将 feign-server 停掉。访问使用hystrix的login-test2和未使用hystrix的login-test3

http://127.0.0.1:4200/login-test3?name=stone&pwd=123


http://127.0.0.1:4200/login-test2?name=stone&pwd=123

上面只是简单的罗列了些主要内容,详情可以看原示例

代码地址:http://download.csdn.net/detail/stonexmx/9774537


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值