上文我们创建了注册中心,以及服务的提供者microservice-provider-user,并成功地将服务提供者注册到了注册中心上。

要想消费microservice-provider-user的服务是很简单的,我们只需要使用RestTemplate即可,或者例如HttpClient之类的http工具也是可以的。但是在集群环境下,我们必然是每个服务部署多个实例,那么服务消费者消费服务提供者时的负载均衡又要如何做呢?

准备工作

  1. 启动注册中心:microservice-discovery-eureka
  2. 启动服务提供方:microservice-provider-user
  3. 修改microservice-provider-user的端口为8002,另外启动一个实例

此时,访问http://discovery:8761

Eureka上面注册2个服务提供者

可以在Eureka中看到microservice-provider-user有两个实例在运行。

下面我们创建一个新的微服务(microservice-consumer-movie-*),负载均衡地消费microservice-provider-user的服务。

负载均衡:Ribbon

Ribbon介绍

Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。简单地说,Ribbon是一个客户端负载均衡器。

Ribbon代码示例

创建一个Maven项目,并在pom.xml中加入如下内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>microservice-consumer-movie-ribbon</artifactId>
    <packaging>jar</packaging>

    <parent>
        <groupId>com.itmuch.cloud</groupId>
        <artifactId>spring-cloud-microservice-study</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

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

        <!-- 整合ribbon -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
</project>

启动类:MovieRibbonApplication.java。使用@LoadBalanced注解,为RestTemplate开启负载均衡的能力。

@SpringBootApplication
@EnableDiscoveryClient
public class MovieRibbonApplication {
    /**
     * 实例化RestTemplate,通过@LoadBalanced注解开启均衡负载能力.
     * @return restTemplate
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

实体类:User.java

public class User {
    private Long id;
    private String username;
    private Integer age;
    ...
    // getters and setters
}

Ribbon的测试类:TestRibbonController.java

@RestController
public class TestRibbonController {
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/ribbon/{id}")
    public User findById(@PathVariable Long id) {
        // http://服务提供者的serviceId/url
        return this.restTemplate.getForObject("http://microservice-provider-user/1", User.class);
    }
}

application.yml

server:
  port: 8011
spring:
  application:
    name: microservice-consumer-movie-ribbon
eureka:
  client:
    serviceUrl:
      defaultZone: http://discovery:8761/eureka/
  instance:
    preferIpAddress: true

启动后,访问多次http://localhost:8011/ribbon/1,返回结果:

{
    "id": 1,
    "username": "Tom",
    "age": 12
}

然后打开两个microservice-provider-user实例的控制台,发现两个实例都输出了类似如下的日志内容:

Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.username as username3_0_0_ from user user0_ where user0_.id=?
2016-08-30 16:25:36.742 TRACE 24404 --- [nio-8002-exec-3] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [1]
2016-08-30 16:25:36.743 TRACE 24404 --- [nio-8002-exec-3] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([age2_0_0_] : [INTEGER]) - [12]
2016-08-30 16:25:36.743 TRACE 24404 --- [nio-8002-exec-3] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([username3_0_0_] : [VARCHAR]) - [Tom]

至此,我们已经通过Ribbon在客户端侧实现了均衡负载。

Feign

Feign介绍

Feign是一个声明式的web service客户端,它使得编写web service客户端更为容易。创建接口,为接口添加注解,即可使用Feign。Feign可以使用Feign注解或者JAX-RS注解,还支持热插拔的编码器和解码器。Spring Cloud为Feign添加了Spring MVC的注解支持,并整合了Ribbon和Eureka来为使用Feign时提供负载均衡。

翻译自:http://projects.spring.io/spring-cloud/docs/1.0.3/spring-cloud.html#spring-cloud-feign

Feign示例

创建一个Maven项目,并在pom.xml添加如下内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>microservice-consumer-movie-feign</artifactId>
    <packaging>jar</packaging>

    <parent>
        <groupId>com.itmuch.cloud</groupId>
        <artifactId>spring-cloud-microservice-study</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

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

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
</project>

启动类:MovieFeignApplication.java

/**
 * 使用@EnableFeignClients开启Feign
 * @author eacdy
 */
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class MovieFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(MovieFeignApplication.class, args);
    }
}

实体类:User.java

public class User {
    private Long id;
    private String username;
    private Integer age;
    ...
    // getters and setters
}

Feign测试类:UserClient.java。

/**
 * 使用@FeignClient("microservice-provider-user")注解绑定microservice-provider-user服务,还可以使用url参数指定一个URL。
 * @author eacdy
 */
@FeignClient(name = "microservice-provider-user")
public interface UserClient {
    @RequestMapping("/{id}")
    public User findById(@RequestParam("id") Long id);
}

Feign的测试类:TestFeignController.java

@RestController
public class TestFeignController {
    @Autowired
    private UserClient userClient;

    @GetMapping("feign/{id}")
    public User test(@PathVariable Long id) {
        User user = this.userClient.findById(id);
        return user;
    }
}

application.yml

server:
  port: 8012
spring:
  application:
    name: microservice-consumer-movie-feign
eureka:
  client:
    serviceUrl:
      defaultZone: http://discovery:8761/eureka/
  instance:
    preferIpAddress: true
ribbon:
  eureka:
    enabled: true         # 默认为true。如果设置为false,Ribbon将不会从Eureka中获得服务列表,而是使用静态配置的服务列表。静态服务列表可使用:<client>.ribbon.listOfServers来指定。参考:http://projects.spring.io/spring-cloud/docs/1.0.3/spring-cloud.html#spring-cloud-ribbon-without-eureka

### 参考:https://spring.io/guides/gs/client-side-load-balancing/

同样的,启动该应用,多次访问[http://192.168.0.59:8012/feign/1,我们会发现和Ribbon示例一样实现了负载均衡。

代码地址(任选其一):

Ribbon代码地址:

http://git.oschina.net/itmuch/spring-cloud-study/tree/master/microservice-consumer-movie-ribbon
https://github.com/eacdy/spring-cloud-study/tree/master/microservice-consumer-movie-ribbon

Feign代码地址:

http://git.oschina.net/itmuch/spring-cloud-study/tree/master/microservice-consumer-movie-feign
https://github.com/eacdy/spring-cloud-study/tree/master/microservice-consumer-movie-feign

服务提供者和服务消费者

“服务提供者”和“服务消费者”的名词是借用的,笔者并没有在Spring Cloud中看到这样的概念。下面这张表格,简单描述了服务提供者/消费者是什么:

名词 概念
服务提供者 服务的被调用方(即:为其他服务提供服务的服务)
服务消费者 服务的调用方(即:依赖其他服务的服务)

服务提供者(microservice-provider-user)

这是一个稍微有点复杂的程序。我们使用spring-data-jpa操作h2数据库,同时将该服务注册到注册中心Eureka中。

创建一个Maven工程,并在pom.xml中添加如下内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>microservice-provider-user</artifactId>
    <packaging>jar</packaging>

    <parent>
        <groupId>com.itmuch.cloud</groupId>
        <artifactId>spring-cloud-microservice-study</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <!-- 添加Eureka的依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>

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

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
</project>

配置文件:application.yml

server:
  port: 8001
spring:
  application:
    name: microservice-provider-user    # 项目名称尽量用小写
  jpa:
    generate-ddl: false
    show-sql: true
    hibernate:
      ddl-auto: none
  datasource:                           # 指定数据源
    platform: h2                        # 指定数据源类型
    schema: classpath:schema.sql        # 指定h2数据库的建表脚本
    data: classpath:data.sql            # 指定h2数据库的insert脚本
logging:
  level:
    root: INFO
    org.hibernate: INFO
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
    com.itmuch.youran.persistence: ERROR
eureka:
  client:
    serviceUrl:
      defaultZone: http://discovery:8761/eureka/    # 指定注册中心的ip
  instance:
    preferIpAddress: true

建表语句:schema.sql

drop table user if exists;
create table user (id bigint generated by default as identity, username varchar(255), age int, primary key (id));

插库语句:data.sql

insert into user (id, username, age) values (1,'Tom',12);
insert into user (id, username, age) values (2,'Jerry', 23);
insert into user (id, username, age) values (3,'Reno', 44);
insert into user (id, username, age) values (4,'Josh', 55);

DAO:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

Controller:

/**
 * 作用:
 * ① 测试服务实例的相关内容
 * ② 为后来的服务做提供
 * @author eacdy
 */
@RestController
public class UserController {
    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private UserRepository userRepository;

    /**
     * 注:@GetMapping("/{id}")是spring 4.3的新注解等价于:
     * @RequestMapping(value = "/id", method = RequestMethod.GET)
     * 类似的注解还有@PostMapping等等
     * @param id
     * @return user信息
     */
    @GetMapping("/{id}")
    public User findById(@PathVariable Long id) {
        User findOne = userRepository.findOne(id);
        return findOne ;
    }

    /**
     * 本地服务实例的信息
     * @return
     */
    @GetMapping("/instance-info")
    public ServiceInstance showInfo(){
        ServiceInstance localServiceInstance = this.discoveryClient.getLocalServiceInstance();
        return localServiceInstance;
    }
}

实体类:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column
    private String username;
    @Column
    private Integer age;
    ...
    //getters and setters...
}

编写Spring Boot启动程序,通过@EnableDiscoveryClient注解,即可将microservice-provider-user服务注册到Eureka上面去

@SpringBootApplication
@EnableDiscoveryClient
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
}

至此,代码编写完成。

我们依次启动Eureka服务和microservice-provider-user服务。

访问:http://localhost:8761,如下图。我们会发现microservice-provider-user服务已经被注册到了Eureka上面了。

microservice-provider-user服务注册到Eureka上

访问:http://localhost:8001/instance-info,返回结果:

{
    "host": "10.0.75.1",
    "port": 8001,
    "metadata": {},
    "uri": "http://10.0.75.1:8001",
    "secure": false,
    "serviceId": "microservice-provider-user"
}

访问:[http://discovery:8001/1,返回结果:

{
    "id": 1,
    "username": "Tom",
    "age": 12
}

代码地址(任选其一):

http://git.oschina.net/itmuch/spring-cloud-study/tree/master/microservice-provider-user
https://github.com/eacdy/spring-cloud-study/tree/master/microservice-provider-user

关于服务发现

在微服务架构中,服务发现(Service Discovery)是关键原则之一。手动配置每个客户端或某种形式的约定是很难做的,并且很脆弱。Spring Cloud提供了多种服务发现的实现方式,例如:Eureka、Consul、Zookeeper。本文暂时只讲述基于Eureka的服务发现。后续会补上基于Consul和Zookeeper的服务发现。

Eureka Server示例

创建一个Maven工程(microservice-discovery-eureka),并在pom.xml中加入如下内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>microservice-discovery-eureka</artifactId>
    <packaging>jar</packaging>

    <parent>
        <groupId>com.itmuch.cloud</groupId>
        <artifactId>spring-cloud-microservice-study</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

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

编写Spring Boot启动程序:通过@EnableEurekaServer申明一个注册中心

/**
 * 使用Eureka做服务发现.
 * @author eacdy
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

在默认情况下,Eureka会将自己也作为客户端尝试注册,所以在单机模式下,我们需要禁止该行为,只需要在application.yml中如下配置:

server:
  port: 8761                    # 指定该Eureka实例的端口

eureka:
  instance:
    hostname: discovery         # 指定该Eureka实例的主机名
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

# 参考文档:http://projects.spring.io/spring-cloud/docs/1.0.3/spring-cloud.html#_standalone_mode
# 参考文档:http://my.oschina.net/buwei/blog/618756

启动工程后,访问:http://discovery:8761/,如下图。我们会发现此时还没有服务注册到Eureka上面。

Eureka首页

代码地址(任选其一):

http://git.oschina.net/itmuch/spring-cloud-study/tree/master/microservice-discovery-eureka
https://github.com/eacdy/spring-cloud-study/tree/master/microservice-discovery-eureka

什么是微服务架构

近年来,在软件开发领域关于微服务的讨论呈现出火爆的局面,有人倾向于在系统设计与开发中采用微服务方式实现软件系统的松耦合、跨部门开发;同时,反对之声也很强烈,持反对观点的人表示微服务增加了系统维护、部署的难度,导致一些功能模块或代码无法复用,同时微服务允许使用不同的语言和框架来开发各个系统模块,这又会增加系统集成与测试的难度,而且随着系统规模的日渐增长,微服务在一定程度上也会导致系统变得越来越复杂。尽管一些公司已经在生产系统中采用了微服务架构,并且取得了良好的效果;但更多公司还是处在观望的态度。

什么是微服务架构呢?简单说就是将一个完整的应用(单体应用)按照一定的拆分规则(后文讲述)拆分成多个不同的服务,每个服务都能独立地进行开发、部署、扩展。服务于服务之间通过注入RESTful api或其他方式调用。大家可以搜索到很多相关介绍和文章。本文暂不细表。

在此推荐两个比较好的博客:

http://microservices.io/
http://martinfowler.com/articles/microservices.html

Spring Cloud 简介

Spring Cloud是在Spring Boot的基础上构建的,为开发人员提供快速建立分布式系统中的一些常见的模式

例如:配置管理(configuration management),服务发现(service discovery),断路器(circuit breakers),智能路由( intelligent routing),微代理(micro-proxy),控制总线(control bus),一次性令牌( one-time tokens),全局锁(global locks),领导选举(leadership election),分布式会话(distributed sessions),集群状态(cluster state)。

Spring Cloud 包含了多个子项目:

例如:Spring Cloud Config、Spring Cloud Netflix等

Spring Cloud 项目主页:http://projects.spring.io/spring-cloud/

Talk is cheep, show me the code.下面我们将以代码与讲解结合的方式,为大家讲解Spring Cloud中的各种组件。

准备

环境准备:

工具 版本或描述
JDK 1.8
IDE STS 或者 IntelliJ IDEA
Maven 3.x

主机名配置:

主机名配置(C:\Windows\System32\drivers\etc\hosts文件)
127.0.0.1 discovery configserver gateway

在进入主题之前,我们首先创建一个父项目(spring-cloud-microservice-study),这样可以对项目中的Maven依赖进行统一的管理。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itmuch.cloud</groupId>
    <artifactId>spring-cloud-microservice-study</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>microservice-discovery-eureka</module>
        <module>microservice-provider-user</module>
    </modules>

    <!-- 使用最新的spring-boot版本 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Brixton.SR4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

一、简易安装

操作环境 CentOS6.5 X64,原版本4.4.7,不支持C++11的特性,故而升级到4.8.2。不能通过yum的方法升级,需要自己手动下载安装包并编译

1.1 获取安装包并解压

wget http://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2
tar -jxvf gcc-4.8.2.tar.bz2

当然,http://ftp.gnu.org/gnu/gcc  里面有所有的gcc版本供下载,最新版本已经有4.9.2啦.

1.2 下载供编译需求的依赖项

参考文献[1]中说:这个神奇的脚本文件会帮我们下载、配置、安装依赖库,可以节约我们大量的时间和精力。

cd gcc-4.8.2
./contrib/download_prerequisites

1.3 建立一个目录供编译出的文件存放

mkdir gcc-build-4.8.2
cd gcc-build-4.8.2

1.4 生成Makefile文件

../configure -enable-checking=release -enable-languages=c,c++ -disable-multilib

1.5 编译(注意:此步骤非常耗时)

make -j4

-j4选项是make对多核处理器的优化,如果不成功请使用 ***make***,相关优化选项可以移步至参考文献[2]。

我在安装此步骤时候出错,错误描述:

 

compilation terminated.
make[5]: *** [_gcov_merge_add.o] 错误 1
make[5]: Leaving directory `/home/imdb/gcc-4.8.2/gcc-build-4.8.2/x86_64-unknown-linux-gnu/32/libgcc'
make[4]: *** [multi-do] 错误 1
make[4]: Leaving directory `/home/imdb/gcc-4.8.2/gcc-build-4.8.2/x86_64-unknown-linux-gnu/libgcc'
make[3]: *** [all-multi] 错误 2
make[3]: *** 正在等待未完成的任务....
make[3]: Leaving directory `/home/imdb/gcc-4.8.2/gcc-build-4.8.2/x86_64-unknown-linux-gnu/libgcc'
make[2]: *** [all-stage1-target-libgcc] 错误 2
make[2]: Leaving directory `/home/imdb/gcc-4.8.2/gcc-build-4.8.2'
make[1]: *** [stage1-bubble] 错误 2
make[1]: Leaving directory `/home/imdb/gcc-4.8.2/gcc-build-4.8.2'
make: *** [all] 错误 2

 

大概看看,错误集中在 x86_64unknown-linux-gnu/32/libgcc 和 x86_64-unknown-linux-gnu/libgcc

根据参考文献[3],安装如下两个软件包(仅用于CentOS6.X):

sudo yum -y install glibc-devel.i686 glibc-devel

过程中CPU基本满载:

图

1.6、安装

sudo make install

 

二、验证安装

重启,然后查看gcc版本:

gcc -v

尝试写一个C++11特性的程序段 tryCpp11.cc,使用了shared_ptr

 

 1 //tryCpp11.cc
 2 #include <iostream>
 3 #include <memory>
 4 
 5 int main()
 6 {
 7     std::shared_ptr<int> pInt(new int(5));
 8     std::cout << *pInt << std::endl;
 9     return 0;
10 }

 

验证文件:

g++ -std=c++11 -o tryCpp11 tryCpp11.cc
./tryCpp11

Linux升级GCC 4.8.1清晰简明教程(Ubuntu 12.04 64位版为例)  http://www.linuxidc.com/Linux/2014-04/99583.htm

在CentOS 6.4中编译安装GCC 4.8.1 + GDB 7.6.1 + Eclipse 在CentOS 6.4中编译安装GCC 4.8.1 + GDB 7.6.1 + Eclipse

Ubuntu下Vim+GCC+GDB安装及使用 http://www.linuxidc.com/Linux/2013-01/78159.htm

Ubuntu下两个GCC版本切换 http://www.linuxidc.com/Linux/2012-10/72284.htm

1. 安装Node.js

安装nvm

wget https://github.com/cnpm/nvm/archive/v0.23.0.tar.gz
tar -zxvf v0.23.0.tar.gz  # 解压
cd nvm-0.23.0/
./install.sh  # 执行脚本 这一步在 当前的角色的目录下建一个 .nvm的文件夹  和 设置 ./bashrc 环境变量  如果是root的话 就会在 /root/ 下面
source ~/.bash_profile  # 让设置生效

安装npm

nvm install v4.2.2
加速:
NVM_NODEJS_ORG_MIRROR=https://npm.taobao.org/mirrors/node nvm install 4.2.2

2. 安装Ghost

2.1 下载并解压Ghost 最新版本

cd /opt/software/Ghost
curl https://ghost.org/zip/ghost-0.9.0.zip
unzip ghost-0.9.0.zip

2.2 修改配置文件

cp config.example.js config.js
vim config.js

找到类似production这段,修改成下面这样:

    production: {
        url: 'http://blog.itmuch.com',
        mail: {},
        database: {
            client: 'mysql',
            connection: {
                host:'127.0.0.1',
                user:'mysql用户',
                password:'mysql密码',
                database:'ghost',
                charset:'utf8'
                // filename: path.join(__dirname, '/content/data/ghost.db')
            },
            debug: false
        },

        server: {
            host: '127.0.0.1',
            port: '2368'
        }
    }

3. 编译、启动Ghost

cd /opt/software/Ghost
npm install --production  # 产品模式编译。 如果写npm install 则以开发模式编译

用ghost用户运行ghost(非root账户运行ghost更安全)

adduser -shell /bin/bash --gecos 'ghost blog' ghost
chown -R ghost:ghost /opt/software/Ghost

安装forever,保持Ghost一直在后台运行

cd /var/www/mousycoder
npm install forever -g //全局安装forever模块
NODE_ENV=production forever start index.js //生产模式后台运行ghost

4. 遇到的问题

4.1 Ghost编译失败,异常如下

node-pre-gyp install --fallback-to-build
node-pre-gyp ERR! Tried to download: https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v3.1.4/node-v46-linux-ia32.tar.gz 
node-pre-gyp ERR! Pre-built binaries not found for sqlite3@3.1.4 and node@4.2.2 (node-v46 ABI) (falling back to source compile with node-gyp) 

原因:国内亚马逊c3连不上

https://www.npmjs.com/package/node-pre-gyp

解决方案:

方法1:

npm install v8-profiler --profiler_binary_host_mirror=https://npm.taobao.org/mirrors/node-inspector/
# 如果执行报错,一般是g++的库没有装。先执行yum install gcc-c++

1. 安装MySQL

1.1. 查看是否已经安装过MySQL

rpm -qa|grep mysql

1.2. 卸载mysql (下面是卸载mysql的库,防止产生冲突,mysql也是类似卸载方式)

rpm -e --nodeps mysql-libs-5.1.*
卸载之后,记得:
find / -name mysql
删除查询出来的所有东西

1.3. 安装MySQL

yum install mysql-server

注意: centos 7这样安装不行, 详见其他文章。

1.4. 启动MySQL

启动方式1:service mysqld start
启动方式2:/etc/init.d/mysqld start

1.5. root账户默认是没有密码的,修改root密码

/usr/bin/mysqladmin -u root password 密码 

例如:

/usr/bin/mysqladmin -u root password pwd    # 这样就将root密码设置成pwd了

1.6. 重置root密码(忘记root密码找回)

/etc/init.d/mysqld stop             # 停止MySQL
mysqld_safe --user=mysql --skip-grant-tables --skip-networking &    # 输入绕过密码认证命令
mysql -u root mysql                 # 登录root用户
update user set Password=password ('123456') where user='root'; -- 修改root密码
FLUSH PRIVILEGES;                   -- 数据刷新
quit;                               -- 退出MySQL

1.7. 允许root用户远程登录

1.7.1. MySQL执行命令

GRANT ALL PRIVILEGES ON *.* TO root@'%' IDENTIFIED BY '123456789' WITH GRANT OPTION;

1.7.2. 防火墙开放3306端口

vim /etc/sysconfig/iptables

添加下面一行:

-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT

注意:开通3306 端口的行必须在icmp-host-prohibited所在的行前,否则无效。

1.8. 开机启动MySQL

chkconfig --list | grep mysqld              # 查看MySQL服务是否自动开启
chkconfig mysqld on                         # 配置MySQL服务自动开启

1.9. 将mysql默认引擎设置为InnoDB

vi /etc/my.cnf  # 修改MySQL配置文件my.cnf

在[mysqld]一段加入:

default-storage-engine=InnoDB

删除ib_logfile0、ib_logfile1两个文件

cd /var/lib/mysql
rm -rf ib_logfile*

1.10. 开启MySQL的日志(监控执行的sql语句)

show global variables like '%general%';     # 该语句可以查看是否开启, 以及生成的位置
set global general_log = on;                # 打开  
set global general_log = off;               # 关闭 

1.11. 设置MySQ的编码

vim /etc/my.cnf

搜索到[mysqlld],插入:

collation-server = utf8_unicode_ci 
init-connect = 'SET NAMES utf8' 
character-set-server = utf8

重启MySQL

service mysqld restart

测试

show variables like 'char%';
show variables like 'collation%';  -- 查看是否改成utf-8了否则之后数据库内存中文存放的是乱码,[具体原因](http://www.cnblogs.com/hongfei/archive/2011/12/29/set-names-utf8.html)

1.12. 参考文档

http://blog.csdn.net/fdipzone/article/details/16995303