SpringCloud 微服務 開發步驟

參考:http://blog.didispace.com/springcloud1/
創建一個基礎的Spring Boot工程,每個項目都需加上SpringCloud的依賴
使用的是Brixton版本

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
	    <groupId>org.springframework.cloud</groupId>
	    <artifactId>spring-cloud-dependencies</artifactId>
	    <version>Brixton.RELEASE</version>
	    <type>pom</type>
	    <scope>import</scope>
	</dependency>
    </dependencies>
</dependencyManagement>

一.服務註冊中心

a)加入依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
b)在主程序中加入註解@EnableEurekaServer
    啓動一個服務註冊中心
    
    
c)默認情況下,註冊中心會將自己作爲客戶端需要禁用,配置application.properties
server.port=1111
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/

二.服務提供方

a)加入依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
b)實現處理接口,通過DiscoveryClient獲取信息
@RestController
public class ComputeController {
    private final Logger logger = Logger.getLogger(getClass());
    @Autowired
    private DiscoveryClient client;
    @RequestMapping(value = "/add" ,method = RequestMethod.GET)
    public Integer add(@RequestParam Integer a, @RequestParam Integer b) {
        ServiceInstance instance = client.getLocalServiceInstance();
        Integer r = a + b;
        logger.info("/add, host:" + instance.getHost() + ", service_id:" + instance.getServiceId() + ", result:" + r);
        return r;
    }
}
c)在主類中加入@EnableDiscoveryClient註解
    激活Eureka中的DiscoveryClient實現

d)配置application.properties
#微服務的名稱
spring.application.name=compute-service
server.port=2222
#指定服務註冊中心得位置
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

三.服務消費者

a)Ribbon
    1)加入依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
    2)在應用主類中加入@EnableDiscoveryClient註解
    添加發現服務的能力,創建RestTemplate實例,添加@LoadBalanced註解開啓均衡負載能力
@SpringBootApplication
@EnableDiscoveryClient
public class RibbonApplication {
	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
	public static void main(String[] args) {
		SpringApplication.run(RibbonApplication.class, args);
	}
}
    3)創建ConsumerController來消費,直接通過RestTemplate來調用服務
@RestController
public class ConsumerController {
    @Autowired
    RestTemplate restTemplate;
    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public String add() {
        return restTemplate.getForEntity("http://COMPUTE-SERVICE/add?a=10&b=20", String.class).getBody();
    }
}
    4)配置application.properties
spring.application.name=ribbon-consumer
server.port=3333
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
b)Feign
    1)加入依賴
<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
    2)在應用主類加入@EnableFeignClients註解
    開啓Fegin功能
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignApplication {
	public static void main(String[] args) {
		SpringApplication.run(FeignApplication.class, args);
	}
}
    3)定義想要調用的服務的接口
//通過FeignClient("compute-service")綁定接口對應的service服務
@FeignClient("compute-service")
public interface ComputeClient {
    //是這裏的value在起作用,它映射到服務提供方的方法
    @RequestMapping(method = RequestMethod.GET, value = "/add")
    Integer add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b);
}
    4)在web層調用接口
@RestController
public class ConsumerController {
    @Autowired
    ComputeClient computeClient;
    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public Integer add() {
        return computeClient.add(10, 20);
    }
}
    5)配置application.properties
spring.application.name=feign-consumer
server.port=3333
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

四.斷路器

a)Ribbon引入Hystrix
    1)添加依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
    2)在主類中加入@EnableCircuitBreaker註解
    開啓斷路器功能
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class RibbonApplication {
	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
	public static void main(String[] args) {
		SpringApplication.run(RibbonApplication.class, args);
	}
}
    3)改造原來的服務消費方式,新增ComputeService類,在使用的函數上增加@HystrixCommand註解指定回調方法
@Service
public class ComputeService {
    @Autowired
    RestTemplate restTemplate;
    @HystrixCommand(fallbackMethod = "addServiceFallback")
    public String addService() {
        return restTemplate.getForEntity("http://COMPUTE-SERVICE/add?a=10&b=20", String.class).getBody();
    }
    public String addServiceFallback() {
        return "error";
    }
}
    4)將提rest接口的Controller改爲調用ComputeService的addService
@RestController
public class ConsumerController {
    @Autowired
    private ComputeService computeService;
    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public String add() {
        return computeService.addService();
    }
}
b)Feign使用Hystrix
    1)使用@FeignClient註解中的fallback屬性指定回調類
@FeignClient(value = "compute-service", fallback = ComputeClientHystrix.class)
public interface ComputeClient {
    @RequestMapping(method = RequestMethod.GET, value = "/add")
    Integer add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b);
}
    2)創建回調類ComputeClientHystrix,實現含有@FeignClient註解的接口
@Component
public class ComputeClientHystrix implements ComputeClient {
    @Override
    public Integer add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b) {
        return -9999;
    }
}

五.分佈式配置中心

a)構建Config Server
    1)加入依賴
<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-server</artifactId>
</dependency>
    2)在應用主類中加入@EnableConfigServer註解
    開啓Config Server
@EnableConfigServer
@SpringBootApplication
public class Application {
	public static void main(String[] args) {
		new SpringApplicationBuilder(Application.class).web(true).run(args);
	}
}
    3)配置application.properties,添加服務和git信息
spring.application.name=config-server
server.port=7001
# git管理配置
#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
#訪問git倉庫的用戶名
spring.cloud.config.server.git.username=username
#訪問git倉庫的用戶密碼
spring.cloud.config.server.git.password=password
b)微服務端映射配置
    1)加入依賴
<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
    2)創建bootstrap.properties配置,指定config server
#{application}-{profile}.properties對應的配置文件
spring.application.name=didispace
spring.cloud.config.profile=dev
#對應當前配置的git分支
spring.cloud.config.label=master
#配置中心的地址
spring.cloud.config.uri=http://localhost:7001/
server.port=7002
    3)創建一個Rest Api來返回配置中心的from屬性
@RefreshScope
@RestController
class TestController {
    //通過@Value("${from}")綁定配置服務中配置的from屬性
    @Value("${from}")
    private String from;
    @RequestMapping("/from")
    public String from() {
        return this.from;
    }
}

六.分佈式配置中心(高可用)

a)config-server配置
    1)新增依賴
<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
    2)配置application.properties
spring.application.name=config-server
server.port=7001
# 配置服務註冊中心
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
# git倉庫配置
spring.cloud.config.server.git.uri=http://git.oschina.net/didispace/SpringCloud-Learning/
spring.cloud.config.server.git.searchPaths=Chapter1-1-8/config-repo
spring.cloud.config.server.git.username=username
spring.cloud.config.server.git.password=password
    3)新增@EnableDiscoveryClient註解,將config-server註冊到服務註冊中心
@EnableDiscoveryClient
@EnableConfigServer
@SpringBootApplication
public class Application {
	public static void main(String[] args) {
		new SpringApplicationBuilder(Application.class).web(true).run(args);
	}
}
b)config-client配置
    1)新增依賴
<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
    2)配置bootstrap.properties
spring.application.name=didispace
server.port=7002
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
#開啓通過服務訪問Config Server的功能
spring.cloud.config.discovery.enabled=true
#指定Config Server註冊的服務名
spring.cloud.config.discovery.serviceId=config-server
spring.cloud.config.profile=dev
    3)在應用主類新增@EnableDiscoveryClient註解
    用來發現config-server服務
c)配置刷新
    1)新增依賴
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

七.服務網關

a)使用Zuul
    1)添加依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
    2)在應用主類加入@EnableZuulProxy註解
    開啓Zuul
@EnableZuulProxy
//整合了@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker
@SpringCloudApplication
public class Application {
	public static void main(String[] args) {
		new SpringApplicationBuilder(Application.class).web(true).run(args);
	}
}
    3)配置application.properties
spring.application.name=api-gateway
server.port=5555
c)服務路由
    1)通過url直接映射(不太友好)
# routes to url
zuul.routes.api-a-url.path=/api-a-url/**
zuul.routes.api-a-url.url=http://localhost:2222/
    2)通過serviceId
zuul.routes.api-a.path=/api-a/**
zuul.routes.api-a.serviceId=service-A
zuul.routes.api-b.path=/api-b/**
zuul.routes.api-b.serviceId=service-B
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
d)服務過濾
    1)創建Zuul過濾器
public class AccessFilter extends ZuulFilter  {
    private static Logger log = LoggerFactory.getLogger(AccessFilter.class);
    @Override
    public String filterType() {
        return "pre";
    }
    @Override
    public int filterOrder() {
        return 0;
    }
    @Override
    public boolean shouldFilter() {
        return true;
    }
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
        Object accessToken = request.getParameter("accessToken");
        if(accessToken == null) {
            log.warn("access token is empty");
            //令zuul過濾該請求,不對其進行路由
            ctx.setSendZuulResponse(false);
            //設置了其返回的錯誤碼
            ctx.setResponseStatusCode(401);
            return null;
        }
        log.info("access token ok");
        return null;
    }
}
2)實例化自定義過濾器
@EnableZuulProxy
@SpringCloudApplication
public class Application {
	public static void main(String[] args) {
		new SpringApplicationBuilder(Application.class).web(true).run(args);
	}
	@Bean
	public AccessFilter accessFilter() {
		return new AccessFilter();
	}
}
八.高可用服務註冊中心
    a)創建application-peer1.properties,作爲peer1服務中心的配置,並將serviceUrl指向peer2
spring.application.name=eureka-server
server.port=1111
eureka.instance.hostname=peer1
eureka.client.serviceUrl.defaultZone=http://peer2:1112/eureka/
    b)創建application-peer2.properties,作爲peer2服務中心的配置,並將serviceUrl指向peer1
spring.application.name=eureka-server
server.port=1112
eureka.instance.hostname=peer2
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/
    c)對hosts文件進行轉換
127.0.0.1 peer1
127.0.0.1 peer2
    d)將項目打包(mvn install),通過spring.profiles.active屬性啓動peer1和peer2
java -jar eureka-server-1.0.0.jar --spring.profiles.active=peer1
java -jar eureka-server-1.0.0.jar --spring.profiles.active=peer2
    e)服務註冊與發現
    修改application.properties
spring.application.name=compute-service
server.port=2222
#將服務指向了peer1和peer2
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer2:1112/eureka/

九.消息總線

a)RabbitMQ
    1)擴展config-client-eureka,加入依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
    2)在配置文件中增加關於RabbitMQ的連接和用戶信息
    需要先安裝RabbitMQ,然後創建一個用戶,爲用戶添加角色和權限
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=springcloud
spring.rabbitmq.password=123456
    3)指定刷新範圍
    /bus/refresh接口還提供了destination參數,用來定位具體要刷新的應用程序。比如,我們可以請求/bus/refresh?destination=customers:9000,destination參數除了可以定位具體的實例之外,還可以用來定位具體的服務。定位服務的原理是通過使用Spring的PathMatecher(路徑匹配)來實現,比如:/bus/refresh?destination=customers:**,該請求會觸發customers服務的所有實例進行刷新。
    
    4)架構優化
    在之前的架構中,服務的配置更新需要通過向具體服務中的某個實例發送請求,再觸發對整個服務集羣的配置更新。
    
        1.在Config Server中也引入Spring Cloud Bus,將配置服務端也加入到消息總線中來。
        
        2./bus/refresh請求不在發送到具體服務實例上,而是發送給Config Server,並通過destination參數來指定需要更新配置的服務或實例。
b)Kafka
    1)整合Spring Cloud Bus,替換依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
    2)Kafka的配置

屬性名	說明	默認值
spring.cloud.stream.kafka.binder.brokers	           Kafka的服務端列表	localhost
spring.cloud.stream.kafka.binder.defaultBrokerPort	    Kafka服務端的默認端口,當brokers屬性中沒有配置端口信息時,就會使用這個默認端口	9092
spring.cloud.stream.kafka.binder.zkNodes	           Kafka服務端連接的ZooKeeper節點列表	localhost
spring.cloud.stream.kafka.binder.defaultZkPort	       ZooKeeper節點的默認端口,當zkNodes屬性中沒有配置端口信息時,就會使用這個默認端口
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章